力扣-数组-特定顺序遍历二维数组
54 螺旋矩阵
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 10
-100 <= matrix[i][j] <= 100
按层模拟:不需要记录已经走过的路径,所以执行用时和内存消耗都相对较小
首先设定上下左右边界
其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界
判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案
若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理
不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> ans;
if(matrix.empty()) return ans;
int up = 0;
int down = matrix.size() - 1;
int left = 0;
int right = matrix[0].size() - 1;
while(true) {
for (int i = left; i <= right; ++i) ans.push_back(matrix[up][i]);
if (++up > down) break;
for (int i = up; i <= down; ++i) ans.push_back(matrix[i][right]);
if (--right < left) break;
for (int i = right; i >= left; --i) ans.push_back(matrix[down][i]);
if (--down < up) break;
for (int i = down; i >= up; --i) ans.push_back(matrix[i][left]);
if (++left > right) break;
}
return ans;
}
};
- 时间复杂度:O(mn),其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
- 空间复杂度:O(1)。除了输出数组以外,空间复杂度是常数。
59 螺旋矩阵 II
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1
输出:[[1]]
提示:
1 <= n <= 20
思路一致
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0));
if (n == 0) return res;
int num = 1;
int left = 0, right = n - 1;
int up = 0, down = n - 1;
while (left <= right && up <= down) {
for (int i = left; i <= right; ++i) res[up][i] = num++;
up++;
if (up > down) break;
for (int i = up; i <= down; ++i) res[i][right] = num++;
right--;
if(right < left) break;
for (int i = right; i >= left; --i) res[down][i] = num++;
down--;
for (int i = down; i >= up; --i) res[i][left] = num++;
left++;
}
return res;
}
};
498 对角线遍历
给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,4,7,5,3,6,8,9]
解释:
说明:
给定矩阵中的元素总数不会超过 100000 。
模拟行走路线
- 知道该对角线的行走方向。
- 确定对角线的起点元素
算法
-
初始化一个布尔变量 direction 表示当前对角线的方向。根据当前方向和尾部位置确定下一条对角线首部。最初 direction 为 1,方向向上。每条对角线遍历完成后更新 direction。
-
假设当前对角线首部为 matrix[i][j],根据方向遍历该对角线。
向上的对角线,下一个元素是 matrix[i−1][j+1]。
向下的对角线,下一个元素是 matrix[i+1][j−1]。 -
遍历当前对角线元素直到到达矩阵边界结束。
-
假设现在到达当前对角线的最后一个元素,寻找下一条对角线首部。注意:下面伪代码中方向是当前对角线方向。如果当前对角线方向是向上的,则下一条对角线是向下的;否则是下一条对角线是向上的。
-
继续处理对角线元素,当前对角线遍历结束时,使用当前方向和尾部位置找出下一条对角线首部。然后翻转方向,处理下一条对角线。
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
if(matrix.empty()) return {};
int N = matrix.size();
int M = matrix[0].size();
int row = 0, column = 0;
int direction = 1; //初始化一个布尔变量direction表示当前对角线的方向 最初direction为1,方向向上
vector<int> result(N*M, 0);
int r = 0;
while (row < N && column < M) {
result[r++] = matrix[row][column];
int new_row = row + (direction == 1 ? -1 : 1); // 方向 行
int new_column = column + (direction == 1 ? 1 : -1); // 方向 列
if (new_row < 0 || new_row == N || new_column < 0 || new_column == M) { // 边界条件
if (direction == 1) {
row += (column == M - 1 ? 1 : 0);
column += (column < M - 1 ? 1 : 0);
} else {
column += (row == N - 1 ? 1 : 0);
row += (row < N - 1 ? 1 : 0);
}
direction = 1 - direction;
} else {
row = new_row;
column = new_column;
}
}
return result;
}
};
- 时间复杂度:O(N⋅M),每个元素只处理一次。
- 空间复杂度:O(1),不使用额外空间。注意:输出数组空间不计入空间复杂度,因为这是题目要求的空间。空间复杂度应该指除了最终数组以外的空间。