Leetcode 498对角线遍历详解:Python与Java实现对比
对角线遍历矩阵:算法详解与实现
给定一个 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 完全一致,仅语法差异。核心是利用布尔标志记录当前方向,每次移动后执行边界矫正,牢记先判断上界、后判断下界的顺序即可。
