1. 矩阵遍历:LeetCode刷题的核心基本功
矩阵遍历是算法学习中最基础却最重要的技能之一。作为LeetCode上出现频率最高的题型之一,掌握矩阵遍历技巧不仅能解决约30%的二维数组相关题目,更是动态规划、图论等高级算法的基础。我在刷完500+道LeetCode题目后发现,90%的矩阵类题目都可以通过四种基本遍历方式及其变种来解决。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 矩阵遍历的四种基本形态
2.1 顺序遍历:最直接的访问方式
顺序遍历是最基础的遍历方式,通常使用双层循环实现:
python复制for i in range(len(matrix)):
for j in range(len(matrix[0])):
print(matrix[i][j])
这种遍历方式在解决矩阵求和、查找特定元素等问题时非常有效。时间复杂度为O(mn),空间复杂度O(1)。
注意:Python中避免使用
len(matrix[0])获取列数,当矩阵为空时会引发异常。建议先检查if not matrix: return
2.2 螺旋遍历:面试高频考点
螺旋遍历要求按照顺时针方向从外向内逐层访问元素,是Google、Meta等公司的高频面试题。实现关键在于维护四个边界:
python复制def spiralOrder(matrix):
if not matrix: return []
res = []
top, bottom = 0, len(matrix)-1
left, right = 0, len(matrix[0])-1
while True:
for i in range(left, right+1): # 从左到右
res.append(matrix[top][i])
top += 1
if top > bottom: break
for i in range(top, bottom+1): # 从上到下
res.append(matrix[i][right])
right -= 1
if left > right: break
for i in range(right, left-1, -1): # 从右到左
res.append(matrix[bottom][i])
bottom -= 1
if top > bottom: break
for i in range(bottom, top-1, -1): # 从下到上
res.append(matrix[i][left])
left += 1
if left > right: break
return res
2.3 对角线遍历:有趣的变种
对角线遍历要求按照对角线方向交替遍历,常用于图像处理等领域。关键点在于判断遍历方向:
python复制def findDiagonalOrder(matrix):
if not matrix: return []
m, n = len(matrix), len(matrix[0])
res = []
for s in range(m + n - 1):
if s % 2 == 0: # 向上遍历
i = min(s, m-1)
j = s - i
while i >= 0 and j < n:
res.append(matrix[i][j])
i -= 1
j += 1
else: # 向下遍历
j = min(s, n-1)
i = s - j
while j >= 0 and i < m:
res.append(matrix[i][j])
i += 1
j -= 1
return res
2.4 旋转遍历:考察维度转换能力
矩阵旋转是经典问题,要求原地旋转90度。核心在于找到元素旋转后的位置关系:
python复制def rotate(matrix):
n = len(matrix)
# 先转置矩阵
for i in range(n):
for j in range(i, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
# 再水平翻转
for i in range(n):
matrix[i] = matrix[i][::-1]
3. 矩阵遍历的实战应用
3.1 岛屿类问题
LeetCode 200题"岛屿数量"是矩阵DFS遍历的经典应用:
python复制def numIslands(grid):
if not grid: return 0
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1':
dfs(grid, i, j)
count += 1
return count
def dfs(grid, i, j):
if i<0 or j<0 or i>=len(grid) or j>=len(grid[0]) or grid[i][j]!='1':
return
grid[i][j] = '0' # 标记为已访问
dfs(grid, i+1, j)
dfs(grid, i-1, j)
dfs(grid, i, j+1)
dfs(grid, i, j-1)
3.2 动态规划中的矩阵遍历
LeetCode 64题"最小路径和"展示了矩阵遍历在DP中的应用:
python复制def minPathSum(grid):
if not grid: return 0
m, n = len(grid), len(grid[0])
dp = [[0]*n for _ in range(m)]
dp[0][0] = grid[0][0]
# 初始化第一行和第一列
for i in range(1, m):
dp[i][0] = dp[i-1][0] + grid[i][0]
for j in range(1, n):
dp[0][j] = dp[0][j-1] + grid[0][j]
# 动态规划填表
for i in range(1, m):
for j in range(1, n):
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
return dp[-1][-1]
4. 矩阵遍历的优化技巧
4.1 边界条件处理
处理矩阵问题时,边界检查是常见错误源。我总结了一个通用模板:
python复制def safe_access(matrix, i, j, default=None):
if 0 <= i < len(matrix) and 0 <= j < len(matrix[0]):
return matrix[i][j]
return default
4.2 方向数组的使用
在DFS/BFS遍历中,使用方向数组可以简化代码:
python复制directions = [(-1,0),(1,0),(0,-1),(0,1)] # 上下左右
for di, dj in directions:
new_i, new_j = i + di, j + dj
if 0 <= new_i < m and 0 <= new_j < n:
# 处理相邻单元格
4.3 原地修改技巧
很多题目要求原地修改矩阵来节省空间。这时可以使用特殊值标记:
python复制# 标记已访问的单元格
matrix[i][j] = '#'
# 或者使用位运算保留原始值
matrix[i][j] ^= 256 # 假设原始值小于256
5. 常见错误与调试技巧
5.1 索引越界问题
矩阵遍历中最常见的错误是索引越界。我建议:
- 始终先检查矩阵是否为空
- 使用
len(matrix)和len(matrix[0])获取行列数时注意顺序 - 在递归调用前检查边界条件
5.2 循环变量混淆
在多层嵌套循环中容易混淆循环变量。我的习惯是:
- 外层循环用
i表示行,内层用j表示列 - 对于复杂循环,使用有意义的变量名如
row,col
5.3 方向遍历的顺序错误
螺旋遍历等复杂遍历容易弄错方向顺序。调试时可以:
- 先在小矩阵(3x3)上手动模拟
- 打印每一步的边界值和当前访问位置
- 使用可视化工具观察遍历路径
6. 矩阵遍历的进阶训练
6.1 推荐练习题目
- LeetCode 54:螺旋矩阵
- LeetCode 48:旋转图像
- LeetCode 73:矩阵置零
- LeetCode 289:生命游戏
- LeetCode 378:有序矩阵中第K小的元素
6.2 训练建议
- 先掌握基础遍历,再挑战变形题目
- 对于每道题,尝试至少两种解法
- 记录每种解法的时间/空间复杂度
- 总结同类题目的解题模板
6.3 性能优化思路
- 对于有序矩阵,考虑二分查找
- 对于稀疏矩阵,使用特殊数据结构存储
- 利用矩阵特性(对称性、特殊模式)优化算法
- 在可能的情况下进行并行计算
矩阵遍历看似简单,但要做到快速准确地解决各种变种题目,需要大量的练习和经验积累。我在面试中发现,即使是资深工程师,在面对复杂的矩阵遍历问题时也常会犯错。建议从基础题目开始,逐步构建自己的解题框架,最终达到看到题目就能想到解法的境界。
