54. 螺旋矩阵
题目:给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
链接 https://leetcode.cn/problems/spiral-matrix/
个人思路
- 根据前面做过的题LeetCode 59. 螺旋矩阵 II代码进行改动,这里不一样的就是这个并不是一个方阵,直接使用之前的代码是不可行的,因为当m=1或者n=1时候会出现重复,走回已经走过的路,刚开始是将这两种单独列出来讨论:
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
ans = []
m = len(matrix)-1
n = len(matrix[0])-1
if m == 0:
return matrix[0]
if n == 0:
for i in matrix:
ans.append(i[0])
return ans
l,r,t,b = 0,n,0,m
num = 1
while num <= (m+1) * (n+1):
# 左到右
for i in range(l,r+1):
ans.append(matrix[l][i])
num += 1
t += 1
# 上到下
for i in range(t,b+1):
ans.append(matrix[i][r])
num += 1
r -= 1
# 右到左
for i in range(r,l-1,-1):
ans.append(matrix[b][i])
num += 1
b -= 1
# 下到上
for i in range(b,t-1,-1):
ans.append(matrix[i][l])
num += 1
l += 1
return ans
在用例[[1,2,3,4],[5,6,7,8],[9,10,11,12]]返回[1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7, 6]说明这里还是会往回走一步,所以下面进行改进:要想右到左,必须bottom大于等于top;同理,要想下到上, 必须right大于等于left
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
ans = []
m = len(matrix)-1
n = len(matrix[0])-1
# if m == 0:
# return matrix[0]
# if n == 0:
# for i in matrix:
# ans.append(i[0])
# return ans
l,r,t,b = 0,n,0,m
num = 1
while num <= (m+1) * (n+1):
# 左到右
for i in range(l,r+1):
ans.append(matrix[l][i])
num += 1
t += 1
# 上到下
for i in range(t,b+1):
ans.append(matrix[i][r])
num += 1
r -= 1
# 右到左,必须bottom大于等于top所在下标
if b >= t:
for i in range(r,l-1,-1):
ans.append(matrix[b][i])
num += 1
b -= 1
# 下到上
if r >= l:
for i in range(b,t-1,-1):
ans.append(matrix[i][l])
num += 1
l += 1
return ans
复杂度分析
复杂度分析
时间复杂度:O(mn),其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
空间复杂度:O(mn)。需要创建一个大小为 m×n 的矩阵 visited 记录每个位置是否被访问过。
其他思路
- 官解模拟写法
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix or not matrix[0]:
return list()
rows, columns = len(matrix), len(matrix[0])
visited = [[False] * columns for _ in range(rows)]
total = rows * columns
order = [0] * total
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
row, column = 0, 0
directionIndex = 0
for i in range(total):
order[i] = matrix[row][column]
visited[row][column] = True
nextRow, nextColumn = row + directions[directionIndex][0], column + directions[directionIndex][1]
if not (0 <= nextRow < rows and 0 <= nextColumn < columns and not visited[nextRow][nextColumn]):
directionIndex = (directionIndex + 1) % 4
row += directions[directionIndex][0]
column += directions[directionIndex][1]
return order
- 按层模拟
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix or not matrix[0]:
return list()
rows, columns = len(matrix), len(matrix[0])
order = list()
left, right, top, bottom = 0, columns - 1, 0, rows - 1
while left <= right and top <= bottom:
for column in range(left, right + 1):
order.append(matrix[top][column])
for row in range(top + 1, bottom + 1):
order.append(matrix[row][right])
if left < right and top < bottom:
for column in range(right - 1, left, -1):
order.append(matrix[bottom][column])
for row in range(bottom, top, -1):
order.append(matrix[row][left])
left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1
return order
- 评论区
用计数判断是否遍历完挺好,只要计数没有到0,肯定是不会越界的
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
r = len(matrix)
c = len(matrix[0])
# print(f"r = {r}, c = {c}")
if r == 1 or c == 1:
return [item for sublist in matrix for item in sublist]
res = []
l = 0
t = 0
right = c - 1
b = r - 1
tmp = len(matrix) * len(matrix[0])
while tmp >= 1:
# print(f"tmp = {tmp}, res = {res}, l = {l}, t = {t}, right = {right}, b = {b}")
# right: fix row
for i in range(l, right + 1):
if tmp >= 1:
res.append(matrix[t][i])
tmp -= 1
t += 1
# down: fix column
for i in range(t, b + 1):
if tmp >= 1:
res.append(matrix[i][right])
tmp -= 1
right -= 1
# left: fix row
for i in range(right, l - 1, -1):
if tmp >= 1:
res.append(matrix[b][i])
tmp -= 1
b -= 1
# up: fix column
for i in range(b, t - 1, -1):
if tmp >= 1:
res.append(matrix[i][l])
tmp -= 1
l += 1
return res
参考:
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/spiral-matrix/solution/luo-xuan-ju-zhen-by-leetcode-solution/