目录
一、54. 螺旋矩阵
模拟
不会,来自题解(. - 力扣(LeetCode))。
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
# 模拟
ans = []
m, n = len(matrix), len(matrix[0])
l, r = 0, n - 1 # 左右边界
u, d = 0, m - 1 # 上下边界
cnt = m * n
while True:
for j in range(l, r + 1):
ans.append(matrix[u][j])
u += 1
if u > d: break
for i in range(u, d + 1):
ans.append(matrix[i][r])
r -= 1
if l > r: break
for j in range(r, l - 1, -1):
ans.append(matrix[d][j])
d -= 1
if u > d: break
for i in range(d, u - 1, -1):
ans.append(matrix[i][l])
l += 1
if l > r: break
return ans
二、59. 螺旋矩阵 II
模拟
和上一道题类似,只是从取值变成了放值。
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
# 模拟
# 按照顺序放即可
cnt = 1
ans = [[0] * n for _ in range(n)]
left, right, up, down = 0, n - 1, 0, n - 1
while True:
for j in range(left, right + 1):
ans[up][j] = cnt
cnt += 1
up += 1
if up > down: break
for i in range(up, down + 1):
ans[i][right] = cnt
cnt += 1
right -= 1
if right < left: break
for j in range(right, left - 1, -1):
ans[down][j] = cnt
cnt += 1
down -= 1
if down < up: break
for i in range(down, up - 1, -1):
ans[i][left] = cnt
cnt += 1
left += 1
if left > right: break
return ans
优化
去掉里面的判断,参考题解(. - 力扣(LeetCode))。
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
# 模拟
# 按照顺序放即可
cnt = 1
ans = [[0] * n for _ in range(n)]
left, right, up, down = 0, n - 1, 0, n - 1
while cnt <= n * n:
# 当l, r等时,for不会循环
for j in range(left, right + 1):
ans[up][j] = cnt
cnt += 1
up += 1
for i in range(up, down + 1):
ans[i][right] = cnt
cnt += 1
right -= 1
for j in range(right, left - 1, -1):
ans[down][j] = cnt
cnt += 1
down -= 1
for i in range(down, up - 1, -1):
ans[i][left] = cnt
cnt += 1
left += 1
return ans
博主将这个方法应用于第一题,发现运行超时了。对比后发现,第一题为矩阵而第二题为正方形。当经历一次while循环,相当于转了一圈。当为正方形时,总结束点总是为一圈的结束点;而当为矩形时,总结束点并不是一圈的结束点。当走到终点时,并没有继续走,但是边界会继续收缩,导致死循环。
三、498. 对角线遍历
模拟-限制对角线的上下界
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
# 模拟
m, n = len(mat), len(mat[0])
ans = []
ux, uy, dx, dy = 0, 0, 0, 0 # 限制对角线的上界和下界
flag = -1 #逆向(左下向右上)
while ux < m and dy < n:
if flag > 0:
# 右上向左下
for i, j in zip(range(ux, dx + 1), range(uy, dy - 1, -1)):
ans.append(mat[i][j])
else:
# 左下向右上
for i, j in zip(range(dx, ux - 1, -1), range(dy, uy + 1)):
ans.append(mat[i][j])
flag = - flag # 更新标签
# 更新端点坐标
if uy < n - 1:
# 不是 < n
uy += 1
else:
ux += 1
if dx < m - 1:
dx += 1
else:
dy += 1
return ans
模拟2
m + n - 1条对角线,参考官方题解(. - 力扣(LeetCode))。
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
# 模拟
m, n = len(mat), len(mat[0])
ans = []
for flag in range(m + n - 1):
# m + n - 1条对角线
if flag % 2:
i = 0 if flag < n else flag - n + 1
j = min(flag, n - 1)
while i < m and j >= 0:
ans.append(mat[i][j])
i += 1
j -= 1
else:
i = min(flag, m - 1)
j = 0 if flag < m else flag - m + 1
while i >= 0 and j < n:
ans.append(mat[i][j])
i -= 1
j += 1
return ans
模拟-优化
将两过程合并,来自题解(. - 力扣(LeetCode))。
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
# 模拟-优化
# 将两过程合并
m, n = len(mat), len(mat[0])
ans = []
flag = True
for i in range(m + n - 1):
pm, pn = (m, n) if flag else (n, m)
x = i if i < pm else pm - 1 # 先变的
y = i - x
while x >= 0 and y < pn:
ans.append(mat[x][y] if flag else mat[y][x])
x -= 1
y += 1
flag = not flag
return ans
感谢你看到这里!
一起加油吧!