문제
요약
- 1 ~ 1000 사이의 숫자 n 이 주어지면, 정삼각형의 한 꼭짓점에서 시작해, 반시계 방향 나선형으로 1부터 순서대로 숫자를 써 넣는다. 그 결과를 반환한다.
분류
- 배열
- dx/dy
풀이
1. 내 풀이
- 발상 : 최대한 직관적으로 생각했다. 문제에서 주어진 행동을 실제로 행하며, 결과를 구했다. 이는 문제에서 n 값의 범위를 1 ~ 1000 으로 제한하고 있기에 가능했다. 최악의 경우(n = 1000)에도 리스트 요소의 개수가 (1000 * 1001) // 2 = 50,000,500 이었기에 감당할만 했다. n 제한이 없었다면 이차원 리스트를 사용하는 것도 부담스러웠을 것이다.
- 사방으로 방향_cur 이라는 커서를 변수로 선언하고, 각각 관리했는데, 조금은 깔끔하지 않아 보인다.
- 마지막에 2차원 배열 1차원으로 풀 때, 이중 컴프리헨션(?)을 해야하는데, 그때 두 for 문의 순서에 유의하자.
def solution(n):
arr = [[0] * j for j in range(1, n + 1)]
left_cur = 0; down_cur = n - 1; right_cur = -1; up_cur = 0
max_num = (n * (n + 1)) // 2
current_num = 0
dis = n
arr[0][0] = 1
while True:
#goDown
for i in range(up_cur, up_cur + dis):
current_num += 1
arr[i][left_cur] = current_num
dis -= 1
up_cur += 2
left_cur += 1
if current_num == max_num : break
#goRight
for i in range(left_cur, left_cur + dis):
current_num += 1
arr[down_cur][i] = current_num
dis -= 1
down_cur -= 1
if current_num == max_num : break
#goUp
for i in range(down_cur, down_cur - dis, -1):
current_num += 1
arr[i][right_cur] = current_num
dis -= 1
right_cur -= 1
if current_num == max_num : break
return [val for arr_val in arr for val in arr_val]
2. 프로그래머스 좋아요가 많았던 풀이
- 발상 : 전형적인 dx, dy. 한 문제에 여러 풀이를 알아두는 것은 중요하다.
def solution(n):
dx = [0, 1, -1]; dy=[1, 0, -1]
b = [[0] * i for i in range(1, n + 1)]
x, y = 0, 0
num = 1
d = 0
while num <= (n + 1) * n // 2:
b[y][x] = num
ny = y + dy[d]
nx = x + dx[d]
num+=1
if 0 <= ny < n and 0 <= nx <= ny and b[ny][nx]== 0:
y, x = ny, nx
else:
d = (d + 1) % 3
y += dy[d]
x += dx[d]
return sum(b,[])
3. 최적화 풀이
- <취업과 이직을 위한 프로그래머스 코딩테스트 문제 풀이 전략> 을 참고한 코드입니다. (링크)
- 발상 : dx, dy 와 발상은 비슷하다. 그러나 for 문 범위를 지정하는 부분과 if 문 조건 처리 부분에서 고수의 향기가 물씬 난다. 배워두자.
def solution(n):
res = [[0] * i for i in range(1, n+1)]
y, x = -1, 0
num = 1
for i in range(n):
for _ in range(i, n):
angle = i % 3
# 순서대로 아래 -> 오른쪽 -> 위 (반시계 나선형)
if angle == 0: y += 1
elif angle == 1: x += 1
elif angle == 2: y -= 1; x -= 1
res[y][x] = num
num += 1
return [i for j in res for i in j]