矩阵对角线遍历算法详解:从原理到Java/Python实现
给定一个 M 行 N 列的矩阵,要求按照对角线顺序遍历并返回所有元素。通俗地说,就像下图所示,沿着斜线方向逐个访问矩阵中的数值。这种遍历方式在图像处理和矩阵运算中相当常见。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,4,7,5,3,6,8,9]

说明:矩阵元素总数不超过 100000,因此算法需要高效处理。
先拆解一下核心思路。示例中矩阵的行列索引范围均为 0~2,咱们一步步观察遍历路径:
(0,0) → (0,1) → (1,0) → (2,0) → (1,1) → (0,2) → (1,2) → (2,1) → (2,2)
坐标 (m, n) 的运动规律其实只有两种方向:
方向一:(m-1, n+1) —— 向右上角移动
方向二:(m+1, n-1) —— 向左下角移动
从 (0,0) 出发,先尝试方向一(右上)。结果 (0,0) → (-1,1),m 变成 -1,超出上边界。越界后怎么处理?将 m 修正为 0,然后切换方向,改为向左下移动。接着连续执行两次左下:(0,1) → (1,0) → (2,-1),n 又越界了,把 n 修正为 0,得到 (2,0)。再次切换为右上,直到下一次越界:
(2,0) → (1,1) → (0,2) → (-1,3)。这次 m 和 n 同时越界(m<0 且 n>2),需特别处理:先判断 n 是否越界,执行 (m+2, n-1) 得到 (1,2),这样能避免因 m<0 而错误切换两次方向。之后一切正常:
(1,2) → (2,1) → (3,0),m 又越界了,切换方向并执行 (m-1, n+2)。
核心逻辑就是用两个方向交替行走,遇到边界时修正坐标并切换方向,尤其注意同时越界时的处理顺序。
Java 实现如下:
class Solution {
public int[] findDiagonalOrder(int[][] matrix) {
if (matrix.length==0||matrix[0].length==0)
return new int[0];
int col=matrix.length,row=matrix[0].length;
int nums=col*row,m=0,n=0;
int res[]=new int[nums];
boolean flag=true;
for(int i=0;i=col){
m-=1; n+=2; flag=true;
}else if(n>=row){
n-=1; m+=2; flag=false;
}
if(m<0){
m=0; flag=false;
}else if(n<0){
n=0; flag=true;
}
}
return res;
}
}
关键注意点:
第一,空数组的判断必须严谨。if (matrix.length==0||matrix[0].length==0) 这个顺序不可颠倒。如果先判断 matrix[0].length==0,当 matrix 本身为空时,访问 matrix[0] 会直接抛出异常。先判断 matrix.length==0 利用短路机制,能安全地返回空数组。
第二,在 for 循环中,每次先根据方向更新坐标后,需要先检查 m 或 n 是否大于等于各自的最大长度,然后再处理小于 0 的情况。这样设计的目的是避免 m、n 同时小于 0 时 flag 被错误翻转两次。执行顺序至关重要。
Python 实现:
class Solution:
def findDiagonalOrder(self, matrix: List[List[int]]) -> List[int]:
if(len(matrix)==0 or len(matrix[0])==0):
return []
col=len(matrix)
row=len(matrix[0])
nums=col*row
m=n=0
flag=True
res=[]
for i in range(nums):
res.append(matrix[m][n])
if flag:
m-=1
n+=1
else:
m+=1
n-=1
if m>=col:
m-=1
n+=2
flag=True
elif n>=row:
m+=2
n-=1
flag=False
if m<0:
m=0
flag=False
elif n<0:
n=0
flag=True
return res
逻辑与 Java 版本完全一致,只是语法差异。核心就是利用一个布尔标志位记录当前方向,每次移动后做边界矫正,并牢记先判断上边界、后判断下边界的顺序即可。
