코드카타 문제 풀이 및 도전 문제 풀이

김민재·2024년 8월 28일
0

코드카타

73.공원 산책
강아지 로봇이 공원을 산책하는 알고리즘인데
특이 사항으로는
로봇 강아지는 이동을 할 때 공원의 범위를 벗어나거나 장애물이 있을 경우에 해당 행동을 중지하고 다음 행동을 실행한다.고
로봇 강아지의 시작위치와 공원의 넒이를 적어둔 park 배열과 로봇 강아지의 행동을 순서대로 적어둔 routes 배열을 통하여 처리해야만 한다.

1.park와 routes 배열은 각각 1차원 배열로 적혀있었기에 이를 먼저 2차원 배열로 바꾸어 알아보기 쉽게 하였다.

2.S의 위치를 찾기 위해 park로 for문을 돌려 배열 내부에 'S'값이 있는지 확인하고 값이 있었을 경우에 routes의 [0][0]값과 [0][1]의 값을 불러와 switch~case문으로 처리하였다.

if (park[i].indexOf('S') !== -1) {
            let s_Save = Number(park[i].indexOf('S'));
            let r0 = routes[0][0];
            let r1 = Number(routes[0][1]);

            let check = true;
            switch (r0) {
                case 'E':
                    if (park[i][s_Save + r1] !== undefined) {
                        for (let j = s_Save; j <= s_Save + r1; j++) {
                            if (park[i][j] === 'X') {
                                check = false;
                                break;
                            }
                        }
                    }
                    else {
                        check = false;
                    }

                    if (check === true) {
                        park[i][s_Save + r1] = 'S';
                        park[i][s_Save] = 'O'
                    }
                    break;

                case 'W':
                    if (park[i][s_Save - r1] !== undefined) {
                        for (let j = s_Save - r1; j < s_Save; j++) {
                            if (park[i][j] === 'X') {
                                check = false;
                                break;
                            }
                        }

                    }
                    else {
                        check = false;
                    }

                    if (check === true) {
                        park[i][s_Save - r1] = 'S';
                        park[i][s_Save] = 'O'
                    }
                    break;

                case 'S':
                    if (park[i + r1] !== undefined) {
                        //park.length로 비교하는게 문제였다.
                        for (let j = i; j <= i + r1; j++) {
                            if (park[j][s_Save] === 'X') {
                                check = false;
                                break;
                            }
                        }
                    }
                    else {
                        check = false;
                    }

                    if (check === true) {
                        park[i + r1][s_Save] = 'S';
                        park[i][s_Save] = 'O'
                    }
                    break;
                case 'N':
                    if (park[i - r1] !== undefined) {
                        for (let j = i - r1; j < i; j++) {
                            if (park[j][s_Save] === 'X') {
                                check = false;
                                break;
                            }
                        }
                    }
                    else {
                        check = false;
                    }

                    if (check === true) {
                        park[i - r1][s_Save] = 'S';
                        park[i][s_Save] = 'O'
                    }
                    break;
            }
            i = -1;
            routes.shift();


        }
    }

여기서 각 케이스마다 for문이 돌아갈 떄 주의해야할 점이 있었는데 해당 배열의 끝,시작점(length,0)을 기준으로 삼아서 for문을 돌리게 될 경우 고려하지 않아도 될 범위마저 고려하게 되기 때문에 범위를 i - r1과 같이 해당 범위에서 벗어나지 않게끔 잡는게 중요했다.

이를 통해 완성된 배열을

for문을 통하여 S의 값의 위치를 찾아 리턴하여 끝.

도전 문제 풀이

1.두산 베어스의 득점 문제

오늘, 두산 베어스와 기아 타이거스가 야구 경기를 하고 있습니다. 이제, 두산 베어스의 공격 차례입니다. 현재 주자는 아무도 없지만, 두산 베어스는 계속해서 1루타(안타)를 치기 시작합니다. 안타를 칠 때마다 주자들은 1루씩 진루합니다. 두산 베어스가 기아 타이거스보다 더 높은 점수를 얻으려면 최소 몇 개의 안타를 쳐야 할까요?
참고로, 두산 베어스와 기아 타이거스의 점수는 프로그램 실행 시 임의적으로 사용자가 줄 수 있으며 두산 베어스에게 1루타의 신이 강림이 되어 타석을 설 때마다 무조건 1루타를 치는 것이 확정이라고 가정해주세요.

이때 1-2-3-홈 으로 들어오면 득점이 이어지게 되는데 1루타의 신이 강림하여 1루타가 확정이라면 두산은 무한 득점이 가능해지며 안타를 4번째 치게된 후의 경우에 1,2,3루가 가득찬 만루가 되므로 이후의 안타는 칠 때마다 1점씩 올라가게 된다.

이런식으로 안타의 수가 4이하가 될 때는 안타를 4번 칠때마다 득점하고 4번 이후부터는 칠때마다 득점하도록 되어있으며 이는 두산의 점수가 기아의 점수를 역전할 때까지 계속된다.

2.이진 배열 nums와 정수 k가 주어졌을 때 배열에서 최대 k개 만큼 0을 뒤집을 수 있다면 배열의 최대 갯수를 반환하라

const nums = [1,1,1,0,0,0,1,1,1,1,0]
const k = 2

//이진 배열 nums와 정수 k가 주어졌을 때, 
//최대 k개의 0을 1로 뒤집을 수 있다면 배열에서 연속된 1의 최대 개수를 반환하세요.

let num_copy = nums.slice();

let zCount = 0; //zeroCount
let oCount = 0; //oneCount
let result = 0;


for(let i = 0 ; i < num_copy.length; i++) {
    //0. 0에 해당하는 값들을 1로 바꾸고 count를 한다.
      if(num_copy[i] === 0) {
         num_copy[i] = 1;
         zCount++;        
      }

      //1.0이 k에 해당하는 값에 도달 했을 때 => 1로 바꿀수있는 0의 최대갯수가 되었을 때.
      if(zCount === k) {
        //2.반복문을 열어서 
         for(let j = 0 ; j < num_copy.length; j++) {
            //2-1. num_copy[j]의 값이 1에 해당하는 것을 세고
            if(num_copy[j] === 1) {
                oCount++;
            }
            //2-2. num_copy[j]의 값이 0이 된다면
            else {
                //세려놓은 oCount가 더 많을 경우엔 덮어 씌우고 oCount를 0으로 만든다.
                if(result < oCount) {
                    result = oCount;
                }
                oCount = 0;
            }
         }

         //3-1.zCount의 값을 초기화한다. => 다시 세어야만 하기때문
         console.log(oCount);
         zCount = 0;
         //i의 값을 0에서 i-1중에 i-1부터 세려서 1의 값에 해당하는 index값을 i값에 저장하게 된다.
         i = num_copy.lastIndexOf(1,i-1);
         console.log(i);
         console.log(num_copy);
         //num_copy의 값은 1로 채워져있어서 변수를 발생시킬수 있기에 초기화시킨다.
         num_copy = nums.slice(); 
               
      }
}
console.log(result);

여러모로 생각을 해보면서 짜다보니까 코드가 많이 복잡해보인다고 생각했다.

좀더 심플한 방법이 있는데

const nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1]
const k = 3



let MaxLength = 0;

for(let i = 0 ; i < nums.length; i++) {   
    let zCount = 0;

    for(let j = i ; j < nums.length; j++) {
        if(nums[j] === 0) {
            zCount++;
        }

        if(zCount > k) {
            break;
        }

        MaxLength = Math.max(MaxLength, j - i + 1); //1,2,3,4,5,6,7,8,9....
    }
}

console.log(MaxLength);

최대 길이가 j가 반복될 때마다 MaxLength와 값을 비교하여 1,2,3,4,5... 씩 계속 증가하는 방식으로 한다면 코드가 단순해진다.

3.클래식과 팝의 비교

스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.
1. 속한 노래가 많이 재생된 장르를 먼저 수록합니다.
2. 장르 내에서 많이 재생된 노래를 먼저 수록합니다.
3. 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.
노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하세요.

먼저 드는 생각은 클래식과 팝을 각각 객체로 나누어서 처리해야겠다고 생각을 했었다.

클래식일 경우엔 classic_sum(모든 클래식의 합)과 classic 객체에 값을 추가하는 방식으로 팝일 경우엔 pop_sum과 pop 객체에 값을 추가하여 처리하였고 여기서부터 좀 생각이 많이 꼬였다고 본다.

각각 나눈 클래식과 팝 객체를 배열로 처리하고자 한것이다..
그렇기에 괜히 크게 돌아간게 아닐까라고 생각을 한다.

각각 객체를 나누어 해당 객체의 수가 2보다 클 경우에 3개의 값을 가지고 있으므로 이를 정렬해줄 필요성이 있었다.
그렇기에 최소값인 min 값을 구하여 min값에 해당하는 값을 제외한 배열을 만들었다.

그리고 마지막에 서로의 값들을 비교하여 하나식 뽑아내는 방식으로 결론을 냈는데 좀 많이 복잡해보이긴한다.

profile
ㅇㅇ

0개의 댓글