498. 对角线遍历【中等题】【每日一题】
思路:
模拟。对官题解的理解与注释。
设矩阵共有row
行,col
列,矩阵元素个数 n = row*col
。
将每一条对角线从0
开始编号,最后一条编号为 row+col-2
。
遍历每一条对角线,设当前对角线编号为 i
,则如果i
是偶数,说明需要向右上方遍历矩阵;如果i
是奇数,说明需要向左下方遍历矩阵。
向左下方遍历时,每遍历一个位置,元素下标变化为:行+1
,列-1
,我们需要找出起始位置[x,y]
。以第col
根对象线为界,将矩阵分为左上和右下两个区域(边界位置第col
根对角线划为右下区域),当对角线在左上区域时,起始位置为[0,i]
,当对角线在右下区域时,起始位置为[i-col+1,col-1]
。
向右上方遍历时,每遍历一个位置,元素下标变化为:行-1
,列+1
,我们需要找出起始位置[x,y]
。以第col
根对象线为界,将矩阵分为左上和右下两个区域(边界位置第col
根对角线划为右下区域),当对角线在左上区域时,起始位置为[i,0]
,当对角线在右下区域时,起始位置为[row-1,i-row+1]
。
每一次遍历都将遍历到的位置放入长度为n
的ans
数组中,并更新ans
指针。
最后返回ans
。
代码:
class Solution {
public int[] findDiagonalOrder(int[][] mat) {
int row = mat.length,col = mat[0].length;
int n = row * col;
int[] ans = new int[n];
int idx = 0;
//将对角线进行编号,[0,row+col-1),遍历每一条对角线,如果编号是偶数,则方向为 ↗ 如果编号是奇数,则方向为 ↙
for (int i = 0; i < row + col - 1; i++) {
if (i % 2 == 1){// ↙
// x 为 当前遍历的起始行 i 小于列数col 起始行为 0 否则 起始行 为 i-col+1
int x = i < col ? 0 : i - col + 1;
// y 为 当前遍历的起始列 i 小于列数col 起始列为 i 否则 起始列 为 col-1
int y = i < col ? i : col - 1;
//找出起始位置之后,向左下方遍历即可,遇到边界则遍历停止
while (x < row && y >= 0){//向左下方遍历
ans[idx++] = mat[x++][y--];
}
}else {// ↗
// x 为当前遍历的起始行 i 小于行数row 起始行为 i 否则为 row-1
int x = i < row ? i : row - 1;
// y 为当前遍历的起始列 i 小于行数row 起始列为 0 否则为 i-row+1
int y = i < row ? 0 : i - row + 1;
//找出起始位置之后,向右上方遍历即可,遇到边界则遍历停止
while (x >= 0 && y < col){
ans[idx++] = mat[x--][y++];
}
}
}
return ans;
}
}