본문 바로가기
개발/알고리즘

[프로그래머스][LEVEL2] 행렬 테두리 회전하기

by ISA(류) 2021. 11. 4.

# 문제 원문

rows x columns 크기인 행렬이 있습니다. 행렬에는 1부터 rows x columns까지의 숫자가 한 줄씩 순서대로 적혀있습니다. 이 행렬에서 직사각형 모양의 범위를 여러 번 선택해, 테두리 부분에 있는 숫자들을 시계방향으로 회전시키려 합니다. 각 회전은 (x1, y1, x2, y2)인 정수 4개로 표현하며, 그 의미는 다음과 같습니다.

  • x1 행 y1 열부터 x2 행 y2 열까지의 영역에 해당하는 직사각형에서 테두리에 있는 숫자들을 한 칸씩 시계방향으로 회전합니다.

행렬의 세로 길이(행 개수) rows, 가로 길이(열 개수) columns, 그리고 회전들의 목록 queries가 주어질 때, 각 회전들을 배열에 적용

한 뒤, 그 회전에 의해 위치가 바뀐 숫자들 중 가장 작은 숫자들을 순서대로 배열에 담아 return 하도록 solution 함수를 완성해주세요.


제한사항

  • rows는 2 이상 100 이하인 자연수입니다.
  • columns는 2 이상 100 이하인 자연수입니다.
  • 처음에 행렬에는 가로 방향으로 숫자가 1부터 하나씩 증가하면서 적혀있습니다.
    • 즉, 아무 회전도 하지 않았을 때, i 행 j 열에 있는 숫자는 ((i-1) x columns + j)입니다.
  • queries의 행의 개수(회전의 개수)는 1 이상 10,000 이하입니다.
  • queries의 각 행은 4개의 정수 [x1, y1, x2, y2]입니다.
    • x1 행 y1 열부터 x2 행 y2 열까지 영역의 테두리를 시계방향으로 회전한다는 뜻입니다.
    • 1 ≤ x1 < x2 ≤ rows, 1 ≤ y1 < y2 ≤ columns입니다.
    • 모든 회전은 순서대로 이루어집니다.
    • 예를 들어, 두 번째 회전에 대한 답은 첫 번째 회전을 실행한 다음, 그 상태에서 두 번째 회전을 실행했을 때 이동한 숫자 중 최솟값을 구하면 됩니다.

입출력 예시

rows / columns / queries / result

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]

# 문제 풀이

 

실제 구현을 다루는 간단한 문제이면서 어려운 문제, 어려운 이유는 지문이 사람 상식과 반대로 되어 있고 입력 값 역시 그렇기 때문이다. 일반적으로 좌표를 다루는 문제는 x, y 차트를 떠올리기 마련이고 그렇기에 x축 y축을 row, col로 인식한다. 근데 이 문제는 그걸 뒤집어 놨다. 진짜 구현이나 기타 조건은 간단한데 지문으로 문제 난이도를 올려놓은 문제이다. 문제 자체는 입력 받은 queries를 하나씩 수행하면서 실제 테이블을 변경하며 가장 작은 값을 구하면 된다.

 

# 솔루션 플로우

1. 입력 받은 rows와 columns 크기의 2차원 배열을 만든다.

2. 입력 받은 queries를 순회하면서 x1, y1, x2, y2 를 구한다.

3. x1, y1, x2, y2 조건에 따라서 오른쪽, 아래, 왼쪽, 위 순서로 해당 영역의 요소를 한칸씩 옮겨준후 그 요소들을 구한다. 

4. 구해진 행렬 요소들 중 가장 작은 수를 구해서 result에 삽입한다.

5. 위의 과정을 queries가 끝날때 까지 반복한다.

6. 얻어진 result를 반환한다.

1. 2차원 배열 & 반복문을 활용한 풀이

function solution(rows, columns, queries) {
    const result = [];
    const table = new Array(rows).fill(true)
        .map((_, rdx) =>
            new Array(columns).fill(true)
                .map((_, cdx) => 1 + rdx * columns + cdx)
        );

    queries.forEach((current) => {
        const prev = [];
        const [x1, y1, x2, y2] = current;
        let r = x1 - 1;
        let c = y1 - 1;
        prev.push(table[r][c]);
        table[r][c] = table[r + 1][c];

        let dire = 'R';
        while (true) {
            if (dire === 'R') {
                if (c + 1 < y2) {
                    c++;
                } else {
                    dire = 'D';
                }
            } if (dire === 'D') {
                if (r + 1 < x2) {
                    r++;
                } else {
                    dire = 'L';
                }
            } if (dire === 'L') {
                if (c - 1 >= y1 - 1) {
                    c--;
                } else {
                    dire = 'U';
                }
            } if (dire === 'U') {
                if (r - 1 > x1 - 1) {
                    r--;
                } else {
                    break;
                }
            }
            prev.push(table[r][c]);
            table[r][c] = prev[prev.length - 2];
        }
        result.push(Math.min(...prev));
    });
    return result;
}
반응형