持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情
题目
给你一个大小为 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 <= 10^4
1 <= m * n <= 10^4
-10^5 <= mat[i][j] <= 10^5
思考
本题难度中等。
首先是读懂题意。给出一个大小为 m x n
的矩阵 mat
,我们需要以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。
首先是观察矩阵,一共有 m + n - 1 条对角线。遍历时我们会得到以下规律:
- 每一趟对角线中元素的坐标(x, y)相加的和是递增的。第一次遍历和为0,第二次和为1,第三次和为2...
- 每次遍历,元素坐标x和y依次递减或递增,幅度为1。
- 确定初始值。比如第二趟,2 的坐标(1, 0),4 的坐标(0, 1)。因此 x + y == 1,x 初始值取 1,y 取 0。
- 确定结束值。坐标的数值不超过矩阵的大小。
因此,我们可以依据以上规律,转化为代码即可。可以看到我们需要for循环遍历一次所有元素,因此所需的时间复杂度为O(m×n)。
解答
方法一:模拟
/**
* @param {number[][]} mat
* @return {number[]}
*/
var findDiagonalOrder = function(mat) {
let nums = []
let m = mat.length, n = mat[0].length
// i 是 x + y 的和
for (let i = 0; i < m + n; i++) {
if (i % 2 === 0) { // 第 1 3 5 ... 趟
// 确定 x y 的初始值
let x1 = (i < m) ? i : m - 1;
let y1 = i - x1;
while (x1 >= 0 && y1 < n) {
nums.push(mat[x1][y1]);
x1--;
y1++;
}
} else { // 第 2 4 6 ... 趟
// 确定 x y 的初始值
let y2 = (i < n) ? i : n - 1;
let x2 = i - y2;
while (y2 >= 0 && x2 < m) {
nums.push(mat[x2][y2]);
x2++;
y2--;
}
}
}
return nums
}
// 执行用时:76 ms, 在所有 JavaScript 提交中击败了96.03%的用户
// 内存消耗:47.2 MB, 在所有 JavaScript 提交中击败了52.24%的用户
// 通过测试用例:32 / 32
复杂度分析:
- 时间复杂度:O(m×n),其中 m 为矩阵行的数量,n 为矩阵列的数量。需要遍历一遍矩阵中的所有元素。
- 空间复杂度:O(1)。除返回值外不需要额外的空间。