题目重述
给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。
示例 1:
输入:mat = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,4,7,5,3,6,8,9]
示例 2:
输入:mat = [[1,2],[3,4]]
输出:[1,2,3,4]
提示:
m == mat.length
n == mat[i].length
1 <= m, n <= 104
1 <= m * n <= 104
-105 <= mat[i][j] <= 105
题解
(可以结合题目给的图来看)
每一趟对角线中元素的坐标(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)。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x 每次-1,y 每次+1。
第三趟:7 的坐标(0, 2), 5 的坐标(1, 1),3 的坐标(2, 0)。x 每次 +1,y 每次 -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和他们各自的上限值是相反的。
x 从大到小,第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x + y == 1
,x 初始值取 1,y 取 0。结束值 x 减到 0 为止。
x 从小到大,第三趟:7 的坐标(0, 2),5 的坐标(1, 1),3 的坐标(2, 0)。x + y == 2,y 初始值取 2,x 取 0。结束值 y 减到 0 为止。
题解参考自:
Java AC
class Solution {
// 2 3
public int[] findDiagonalOrder(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
int[] nums = new int[n*m];
int index = 0;
// i 是 x + y 的和
int i = 0;
// 边界
while (i < m + n) {
// 第 1 3 5 ... 趟
int x1 = (i < m) ? i : m - 1; // 确定 x y 的初始值
int y1 = i - x1;
while (x1 >= 0 && y1 < n)
{
nums[index++]=mat[x1][y1];
x1--;
y1++;
}
i++;
if (i >= m + n) break;
// 第 2 4 6 ... 趟
int y2 = (i < n) ? i : n - 1; // 确定 x y 的初始值
int x2 = i - y2;
while (y2 >= 0 && x2 < m)
{
nums[index++]=mat[x2][y2];
x2++;
y2--;
}
i++;
}
return nums;
}
}