Post

정수를 나선형으로 배치하기

정수를 나선형으로 배치하기

문제 설명

문제 링크


초기 접근 및 로직 구상 방식

문제에서 나선형으로 숫자를 +1씩 증가 시켜 가며 채우는 문제. 어떻게 숫자를 채울까 고민. 예전 CSES 문제였던 계차 수열 문제 처럼 규칙을 찾다가 포기하고, 그냥 방향을 사용하여 조건에 맞게 방향 전환으로 하기로 결정함.

1
2
3
4
5
int[][] direction =  {{0,1},{1,0},{0,-1},{-1,0}}; // 순서대로 오른쪽, 아래, 왼쪽, 위쪽

d = (d + 1) % 4;// 으로 방향 번경

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for(int i = 1; i <= n*n; i++) {
            if(0 <= nextRow && nextRow < n && 0 <= nextCol && nextCol < n && answer[nextRow][nextCol] == 0) {
                answer[nextRow][nextCol] = i;
                curRow = nextRow;
                curCol = nextCol;
                nextRow = curRow + direction[d][0];
                nextCol = curCol + direction[d][1];
                
            } else {
                d = (d + 1) % 4;
                nextRow = curRow + direction[d][0];
                nextCol = curCol + direction[d][1];
            }    
        }

에서 if - else 에서 else 구문으로 들어가도 i는 증가하여, 다 채워지지 못한 상태로 종료가 되어버림.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for(int i = 1; i <= n*n; ) {
            if(0 <= nextRow && nextRow < n && 0 <= nextCol && nextCol < n && answer[nextRow][nextCol] == 0) {
                answer[nextRow][nextCol] = i;
                curRow = nextRow;
                curCol = nextCol;
                nextRow = curRow + direction[d][0];
                nextCol = curCol + direction[d][1];
                i++; // i++ 의 위치를 이동시켜, 배열에 삽입이 되었을때만 실행되도록 바꿈.
                
            } else {
                d = (d + 1) % 4;
                nextRow = curRow + direction[d][0];
                nextCol = curCol + direction[d][1];
            }    
        }

제출

1차 제출

성공함. 허나 코드 내부에 변수가 너무 많아서 지저분해 보인다고 생각함.

1차 제출 코드 (클릭하여 펼치기)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
    public int[][] solution(int n) {
        int[][] answer = new int[n][n];
        int[][] direction = {{0,1},{1,0},{0,-1},{-1,0}};
        int curRow = 0;
        int curCol = 0;
        int d = 0;
        int nextRow = curRow;
        int nextCol = curCol;

        for(int i = 1; i <= n*n;) {
            if(0 <= nextRow && nextRow < n && 0 <= nextCol && nextCol < n && answer[nextRow][nextCol] == 0) {
                answer[nextRow][nextCol] = i;
                curRow = nextRow;
                curCol = nextCol;
                nextRow = curRow + direction[d][0];
                nextCol = curCol + direction[d][1];
                i++;
            } else {
                d = (d + 1) % 4;
                nextRow = curRow + direction[d][0];
                nextCol = curCol + direction[d][1];
            }    
        }

        return answer;
    }
}

2차 제출

그래서 nextCol, nextRow 를 쓰지 않고, col과 rol를 갱신해 다음에 채울 곳으로 이동시키는 방법을 생각해봄.

2차 제출 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
    public int[][] solution(int n) {
        int[][] answer = new int[n][n];
        int[][] direction = {{0,1},{1,0},{0,-1},{-1,0}};
        int row = 0;
        int col = 0;
        int d = 0;

        for(int i = 1; i <= n*n; i++) {

            answer[row][col] = i;

            if(0 <= row + direction[d][0] && row + direction[d][0] < n && 0 <= col + direction[d][1] && col + direction[d][1] < n && answer[row + direction[d][0]][col + direction[d][1]] == 0) {
                row = row + direction[d][0];
                col = col + direction[d][1];
            } else {
                d = (d + 1) % 4;
                row = row + direction[d][0];
                col = col + direction[d][1];
            }    
        }

        return answer;
    }
}

next 변수 없이 현재 col, row를 갱신시켜 다음 지점을 가르키게함. 허나 if문 내부가 오히려 더 보기 풀편해진다는걸 알게됨.

배운 점

  • 변수가 많더라도, 그 변수의 이름과 역할이 명확하면, 놔두는게 더 좋을 수 도 있다고 알게됨. 선택은 쓰는 사람의 몫.
This post is licensed under CC BY 4.0 by the author.