Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- easy
- dfs
- 문자열
- binary tree
- leetcode
- 중간
- recursive
- Array
- HashTable
- sorting
- Depth-first Search
- matrix
- backtracking
- 재귀
- 미디움
- Binary
- 쉬움
- linked list
- Medium
- 리트코드
- tree
- DP
- math
- list
- hash table
- 이진트리
- binary search
- two pointers
- string
- Python
Archives
- Today
- Total
부부의 코딩 성장 일기
LeetCode 59(Spiral Matrix II, Python) 본문
1. 문제 링크
Spiral Matrix II - LeetCode
Can you solve this real interview question? Spiral Matrix II - Given a positive integer n, generate an n x n matrix filled with elements from 1 to n2 in spiral order. Example 1: [https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg] Input: n = 3 O
leetcode.com
2. 문제 설명
- n이 주어지면 n × n 행렬을 만드는데 1부터 n²까지 수를 왼쪽 상단에서 시작해서 회오리 나선 모양으로 넣기
- 54번 문제를 반대 방향으로 푸는 것이다.
- 예시) n = 3이 주어지면 [[1,2,3],[8,9,4],[7,6,5]]을 반환
3. 처음 풀이
- 54번 spiral matrix 1 문제와 비슷하게 풀었다.
- 우선 빈 매트릭스를 만든다.
- 그 다음 val=1 부터 채우면서 1씩 증가시킨다.
- x, y는 행렬의 행, 열의 인덱스이고
- delta_x, delta_y는 +-1의 값을 가져서 오른쪽, 왼쪽 또는 위쪽, 아래쪽 이동을 나타낸다.
- 그리고 up, down, left, right는 경계를 나타내는 인덱스이다.
- delta_x=1이고 x=right이면 오른쪽으로 이동하다가 오른쪽 경계를 만났다는 뜻이므로 이동 방향을 아래쪽으로 바꾸어야 한다.(delta_x=0, delta_y=1) 그리고 오른쪽 경계를 -1하여 왼쪽으로 한 칸 이동.
- 마찬가지로 delta_y=1이고 y=down이면 아래로 이동하다가 아래 경계를 만났다는 뜻이므로 이동 방향을 왼쪽으로 바꾸어야 한다.(delta_x=-1, delta_y=0) 그리고 아래쪽 경계를 +1하여 위로 한 칸 이동.
- 왼쪽 위쪽 경계도 마찬가지로 해주면 된다.
from typing import List
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
# n x n 크기의 행렬을 생성하고 빈 문자열로 초기화
matrix = [['' for _ in range(n)] for _ in range(n)]
# 초기화할 변수들
left = 0
right = n - 1
up = 1
down = n - 1
x, y = 0, 0
delta_x, delta_y = 1, 0
val = 1
# 행렬에 값을 넣어가며 반복
for _ in range(n**2):
matrix[y][x] = val
val += 1
# 방향을 바꾸는 조건문
if delta_x == 1 and x == right:
delta_x, delta_y = 0, 1
right -= 1
elif delta_y == 1 and y == down:
delta_x, delta_y = -1, 0
down -= 1
elif delta_x == -1 and x == left:
delta_x, delta_y = 0, -1
left += 1
elif delta_y == -1 and y == up:
delta_x, delta_y = 1, 0
up += 1
x += delta_x
y += delta_y
# 완성된 행렬 반환
return matrix
4. 다른 풀이
- 나의 풀이와 큰 차이 없지만 그냥 한 줄씩 반복문.
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
mat=[[0 for i in range(n)] for j in range(n)]
val=1
left,right=0,n-1
top,bottom=0,n-1
while left<=right:
#left to right
for i in range(left,right+1):
mat[top][i]=val
val+=1
top+=1
#top to bootom
for i in range(top,bottom+1):
mat[i][right]=val
val+=1
right-=1
#right to left
for i in range(right,left-1,-1):
mat[bottom][i]=val
val+=1
bottom-=1
#bottom to top
for i in range(bottom,top-1,-1):
mat[i][left]=val
val+=1
left+=1
# print(mat)
return mat
- 와 이 풀이 대단하다...
- 끝에 도달하면 시계방향 90도 돌게 된다.
- (x, y)를 시계 방향 90도 회전 변환하면 (y, -x)가 되므로 이동 방향이 di, dj일 때 끝에 도달하면 그 다음 이동 방향은 dj, -di가 된다.
- 처음에 모든 값이 0인 행렬을 만들고 [1,2,3,4]를 채운 후 다시 1을 보면 0이 아니므로 끝에 도달했다는 것을 알 수 있다.
def generateMatrix(self, n):
A = [[0] * n for _ in range(n)]
i, j, di, dj = 0, 0, 0, 1
for k in xrange(n*n):
A[i][j] = k + 1
if A[(i+di)%n][(j+dj)%n]:
di, dj = dj, -di
i += di
j += dj
return A
- 큰 값을 안쪽부터 채운다. 이미 만든 행렬을 회전 후 그 앞의 값을 한 줄 추가하는 것을 1을 넣을 때까지 반복한다. A[::-1]를 하면 역순이 되고 zip하면 회전이 된다.
- 이런 풀이는 어떻게 떠올리는 것인지... 똑똑한 사람들 많다.
|| => |9| => |8| |6 7| |4 5| |1 2 3|
|9| => |9 8| => |9 6| => |8 9 4|
|8 7| |7 6 5|
def generateMatrix(self, n):
A, lo = [], n*n+1
while lo > 1:
lo, hi = lo - len(A), lo
A = [list(range(lo, hi))] + list(zip(*A[::-1]))
return A
5. 배운 점
- (x, y)를 시계 방향 90도 회전 변환하면 (y, -x)가 된다는게 코드 짤 때도 유용하게 쓰인다.
- zip을 이용한 마지막 풀이는 스스로 떠올리기 참 힘들 것 같긴한데.. 무튼 zip은 여기저기서 자주 사용된다. 회전시킬 때도 유용하다.
'Algorithm > LeetCode' 카테고리의 다른 글
LeetCode 62(Unique Paths, Python) (0) | 2024.01.15 |
---|---|
LeetCode 61(Rotate List, Python) (1) | 2024.01.14 |
LeetCode 57(Insert Interval, Python) (0) | 2024.01.12 |
LeetCode 56(Merge Intervals, Python) (1) | 2024.01.11 |
LeetCode 55(Jump Game, Python) (0) | 2024.01.10 |