삼각 달팽이
문제정의
밑변과 높이의 길이가 n인 삼각형이 있고 이를 맨 위 꼭짓점에서부터 반시계방향으로 달팽이를 채우기 하고 열대로 숫자를 담아 출력하는 문제이다. 자세한 그림이 궁금한 사람은 링크를 참고해보길 바란다.
문제풀이
전체 코드는 다음과 같다. 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52public class TriSnail {
//프로그래머스 문제풀이 level2 삼각 달팽이
public static void main(String[] args)
{
int n = 4;
int[][] paper = new int[2*n-1][2*n-1];
int len = n;
int num = 1;
int l_d_move = n%3;
int r_move = l_d_move-1 < 0 ? 2: l_d_move-1;
int r = 0, c = (2*n-1)/2;
while(len != 0)
{
int move_id = len%3;
if(move_id == l_d_move)
{
for(int i = 0; i < len; i++)
paper[r++][c--] = num++;
r--;
c++;
}
else if(move_id == r_move)
{
for(int i = 0; i < len; i++)
{
c+=2;
paper[r][c] = num++;
}
}
else
{
for(int i = 0; i < len; i++)
paper[--r][--c] = num++;
++r;
--c;
}
len--;
}
int idx = 0;
int[] answer = new int[num-1];
for(int i = 0; i < 2*n-1; i++)
{
for(int j = 0; j < 2*n-1; j++)
{
if(paper[i][j] != 0)
answer[idx++] = paper[i][j];
}
}
}
}
그림을 보면 반시계 방향으로 꺽으면서 이동횟수가 1씩 감소하는 것을 볼 수 있다. 삼각형을 그리면서 움직이므로 여기서 규칙을 찾아낼 수 있다. 바로 이동횟수를 3으로 나누고 난 나머지 값을 활용해 어느 방향으로 가야하는지 알 수 있다는 것이다. n=4일 때의 달팽이 채우기를 보자, 4와 1일 때는 왼쪽 아래로 향하는 것을 볼 수 있다. n=5일 때도 보면 같은 규칙이 적용되는 것을 볼 수 있다. 5와 2는 3으로 나눈 나머지가 모두 2이므로, 2일 때 왼쪽 아래로 움직여야 하는 것을 알 수 있다.
규칙을 찾아냈으니 달팽이 채우기를 그릴 틀이 필요하다. 필자는 이것을 paper라고 선언했다. nn으로 2차원배열을 선언하고자 할텐데, 종이와 달리 배열은 중간에 낀 수가 없기 때문에 이렇게 해선 안된다. 2n-1이 길이여야 하는데 이는 아래 그림을 참고하면 왜 그런지 알 수 있다.
핵심 아이디어를 다 익혔으니 코드 세부 구현을 보자. 1
2
3
4
5
6
7int n = 4;
int[][] paper = new int[2*n-1][2*n-1];
int len = n;
int num = 1;
int l_d_move = n%3;
int r_move = l_d_move-1 < 0 ? 2: l_d_move-1;
int r = 0, c = (2*n-1)/2;
1 | while(len != 0) |
move_id에 따라 종이에 숫자를 채워가는 코드이다. r과 c값을 조정해나가면 된다. 범위 때문에 r이나 c값이 이상해지지 않도록 반복문 탈출 뒤 조정해주는 과정도 거친다. 여기서 필자보다 깨끗하게 코드를 짤 수 있을거라 생각하기 때문에, 이 부분에서 더 세부적인 내용은 생략한다. 여기서 시간복잡도는 \(O(n)\)이 되겠다.
1 | int idx = 0; |
이제 paper를 순회하면서 0이 아닌 값을 발견할 때 마다, answer에 값을 넣어주면 된다. 행은 n까지만 보면 되므로, 행의 최대값은 n으로 한다. 이 부분에서 시간복잡도는 \(O(n^2)\)이다. 따라서 최종 시간복잡도는 \(O(n^2)\)이다.
테스트
어떠한 규칙을 찾아내는 냐에 따라 코드가 천차만별인 것 같다. 코드를 좀 더 줄일 수 있는 규칙이 추가로 있는지 고민해봐야겠다.