498. 对角线遍历
题目描述:给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。
思路分析
思路分析
从上图可以得知:
-
每一趟对角线中元素的坐标(x, y)相加的和是递增的。
第一趟:1 的坐标(0, 0)。x + y == 0。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x + y == 1。
第三趟:7 的坐标(0, 2), 5 的坐标(1, 1),3 的坐标(2, 0)。第三趟 x + y == 2。
第四趟:…… -
每一趟都是 x 或 y 其中一个从大到小(每次减 1),另一个从小到大(每次加 1)。
-
确定初始值。例如这一趟是 x 从大到小, x 尽量取最大,当初始值超过 x 的上限时,不足的部分加到 y 上面。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x + y == 1,x 初始值取 1,y 取 0。
第四趟:6 的坐标(2, 1),8 的坐标(1, 2)。x + y == 3,x 初始值取 2,剩下的加到 y上,y 取 1。 -
确定结束值。例如这一趟是 x 从大到小,这一趟结束的判断是,x 减到 0 或者 y 加到上限。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x 减到 0 为止。
第四趟:6 的坐标(2, 1),8 的坐标(1, 2)。x 虽然才减到 1,但是 y 已经加到上限了。 -
这一趟是 x 从大到小,那么下一趟是 y 从大到小,循环进行。 并且方向相反时,逻辑处理是一样的,除了x,y和他们各自的上限值是相反的。
代码实现
public int[] findDiagonalOrder(int[][] mat) {
int m = mat.length,n = mat[0].length;
List<Integer> temp = new ArrayList<>();
int i = 0; // i = x + y
while (i < m + n) {
// 第 1,3,5... 趟
int x1 = i < m ? i : m - 1;
int y1 = i - x1;
while (x1 >= 0 && y1 < n) {
temp.add(mat[x1][y1]);
x1--;
y1++;
}
i++;
if (i >= m + n) break;
// 第 2,4,6... 趟
int y2 = i < n ? i : n - 1;
int x2 = i - y2;
while (y2 >= 0 && x2 < m) {
temp.add(mat[x2][y2]);
x2++;
y2--;
}
i++;
}
int[] result = new int[temp.size()];
for (int j = 0; j < result.length; j++) {
result[j] = temp.get(j);
}
return result;
}