프로그래머스/Lv.2

프로그래머스 JS [행렬 테두리 회전하기] 이차원배열의 깊은복사

sakuraop 2022. 12. 27. 07:33

행렬 테두리 회전하기

이 행렬에 (2, 2, 5, 4) 회전을 적용하면, 아래 그림과 같이 2행 2열부터 5행 4열까지 영역의 테두리가 시계방향으로 회전합니다. 이때, 중앙의 15와 21이 있는 영역은 회전하지 않는 것을 주의하세요.

행렬의 세로 길이(행 개수) rows, 가로 길이(열 개수) columns, 그리고 회전들의 목록 queries가 주어질 때, 각 회전들을 배열에 적용한 뒤, 그 회전에 의해 위치가 바뀐 숫자들 중 가장 작은 숫자들을 순서대로 배열에 담아 return 하도록 solution 함수를 완성해주세요.


입출력 예시rowscolumnsqueriesresult
6 6 [[2,2,5,4],[3,3,6,6],[5,1,6,3]] [8, 10, 25]
3 3 [[1,1,2,2],[1,2,2,3],[2,1,3,2],[2,2,3,3]] [1, 1, 5, 3]
100 97 [[1,1,100,97]] [1]

입출력 예 설명

입출력 예 #1

  • 회전을 수행하는 과정을 그림으로 표현하면 다음과 같습니다.

문제 풀이 

1. rows*columns 배열 생성하기
2. queries 범위의 배열 테두리를 시계방향으로 한 칸씩 이동시키기
3. queries 범위의 배열 테두리 중 최솟값을 result에 추가하기
4. 2~3을 queries의 길이만큼 시행하기


배열 안의 배열을 복사하게 되면 얕은 복사가 되어서 원본 배열의 값이 변합니다.

const array1 = [[1,2,3]] 
const array2 = [...array1]

이렇게 하면 깊은 복사가 되어 원본 배열의 값이 변하지 않을 것으로 생각했습니다.

테스트로 1을 3으로 값을 바꾸어 봅니다.
=>array2[0][0] = array1[0][2] 

출력해봅니다.
=> array2 // [[3,2,3]] 
=> array1 // [[3,2,3]] 

원본 배열의 값이 같이 바뀝니다.

이차원배열에서 깊은 복사를 위해서는
=> const array2 = array1.map(el => [...el]) 

배열 안의 배열마다 깊은 복사를 해주면 됩니다. 

function solution(rows, columns, queries) {
    const result = [];
    // 1. rows*columns 배열 생성하기
    let array = [];
    let number = 1;
    for (let i = 0; i < rows; i++) {
        array.push([]);
        for (let j = 0; j < columns; j++) {
            array[i].push(number);
            number++;
        }
    }

    // 4. 2~3을 queries의 길이만큼 시행하기
    queries.forEach((el) => {
        const edgeElementArray = [];
        // 이차원배열 깊은 복사를 위해서는 배열 원소들을 각각 깊은 복사 해주어야 한다.
        const tempArray = array.map((el) => [...el]);
        const [x1, y1, x2, y2] = [el[0] - 1, el[1] - 1, el[2] - 1, el[3] - 1];
        // 2. queries 배열 범위의 테두리를 시계방향으로 한 칸씩 이동시키기
        for (let i = x1; i <= x2; i++) {
            for (let j = y1; j <= y2; j++) {
                // (i > x1  && j > y1  && i < x2  && j < y2)  중간값 범위의 대우로 중간값 제외
                if (i <= x1 || j <= y1 || i >= x2 || j >= y2) { 
                    if (i === x1 && j !== y1) {
                        tempArray[i][j] = array[i][j - 1];
                        edgeElementArray.push(array[i][j - 1]);
                        continue;
                    }
                    if (i !== x1 && j === y2) {
                        tempArray[i][j] = array[i - 1][j];
                        edgeElementArray.push(array[i - 1][j]);
                        continue;
                    }
                    if (i === x2 && j !== y2) {
                        tempArray[i][j] = array[i][j + 1];
                        edgeElementArray.push(array[i][j + 1]);
                        continue;
                    }
                    if (i !== x2 && j === y1) {
                        tempArray[i][j] = array[i + 1][j];
                        edgeElementArray.push(array[i + 1][j]);
                    }
                }
            }
        }
        // 3. queries 배열 범위의 테두리 중 최솟값을 result에 추가하기
        result.push(Math.min(...edgeElementArray));
        array = tempArray;
    });
    return result;
}

solution(6, 6, [
    [2, 2, 5, 4],
    [3, 3, 6, 6],
    [5, 1, 6, 3],
]);