java 一套组合拳打遍所有螺旋遍历!
54. 螺旋矩阵
题目
给定一个包含 m x n m x n mxn 个元素的矩阵( m m m 行, n n n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
四指针
使用四个指针记录当前要遍历的行/列
大循环内部:
- 向右:遍历第up行,从left -> right; up++,这一行结束;
- 向下:遍历第right列,从up -> down; right–,这一列结束;
- 向左:遍历第down行,从right -> left;down–,这一行结束;
- 向上:遍历第left列,从down -> up;left++,这一列结束。
由于矩形不规则,有可能在任意位置停止,因此每个小循环结束都需要判断下是否已经遍历结束。
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
int m = matrix.length, n = matrix[0].length;
int up = 0, right = n - 1, down = m - 1, left = 0;
while(true){
for(int i = left; i <= right; i++) res.add(matrix[up][i]);
up++;
if(res.size() == m * n) return res;
for(int i = up; i <= down; i++) res.add(matrix[i][right]);
right--;
if(res.size() == m * n) return res;
for(int i = right; i >= left; i--) res.add(matrix[down][i]);
down--;
if(res.size() == m * n) return res;
for(int i = down; i >= up; i--) res.add(matrix[i][left]);
left++;
if(res.size() == m * n) return res;
}
}
}
时间复杂度
O ( n ∗ m ) O(n * m) O(n∗m),遍历所有位置。
空间复杂度
O ( 1 ) O(1) O(1) 使用常数空间额外复杂度。
59. 螺旋矩阵 II
题目
给定一个正整数 n n n,生成一个包含 1 1 1 到 n 2 n_2 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
四指针
和上题类似,四个指针来遍历所有位置,使用 n u m num num记录即可,因为是规则正方形,每次肯定可以走完一圈,因此每次循环最后判断即可。
class Solution {
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
int up = 0, down = n - 1, left = 0, right = n - 1, num = 1;
while(num <= n * n){
for(int i = left; i <= right; i++) res[up][i] = num++;
up++;
for(int i = up; i <= down; i++) res[i][right] = num++;
right--;
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;
}
}
时间复杂度
O ( n ∗ m ) O(n * m) O(n∗m),遍历所有位置。
空间复杂度
O ( 1 ) O(1) O(1) 使用常数空间额外复杂度。
885. 螺旋矩阵 III
题目
在 R R R 行 C C C 列的矩阵上,我们从 ( r 0 , c 0 ) (r_0, c_0) (r0,c0) 面朝东面开始
这里,网格的西北角位于第一行第一列,网格的东南角位于最后一行最后一列。
现在,我们以顺时针按螺旋状行走,访问此网格中的每个位置。
每当我们移动到网格的边界之外时,我们会继续在网格之外行走(但稍后可能会返回到网格边界)。
最终,我们到过网格的所有 R ∗ C R * C R∗C 个空间。
按照访问顺序返回表示网格位置的坐标列表。
示例 1:
输入:R = 1, C = 4, r0 = 0, c0 = 0
输出:[[0,0],[0,1],[0,2],[0,3]]
四指针
忽略是否在界外,直接转圈,那么就相当于在遍历一个大正方形,额外实现一个 c h e c k check check方法,检查如果在界内就记录即可。
本题横竖需要走的格数遵从这样的规律 1 , 1 , 2 , 2 , 3 , 3 , 4 , 4 , . . . 1, 1, 2, 2, 3, 3, 4, 4, ... 1,1,2,2,3,3,4,4,...,因此可以使用两个变量 r o w row row, c o l col col来记录横竖需要走的距离,每次走完一条直线就自增1,简化写法。
class Solution {
int R, C, idx = 1;
int[][] res;
void check(int r0, int c0){
if(r0 >= 0 && r0 < R && c0 >= 0 && c0 < C){
res[idx][0] = r0;
res[idx++][1] = c0;
}
}
public int[][] spiralMatrixIII(int R, int C, int r0, int c0) {
this.R = R; this.C = C;
res = new int[R * C][2];
int row = 1, col = 1;
res[0][0] = r0; res[0][1] = c0;
while(idx < R * C){
for(int i = 1; i <= row; i++) check(r0, ++c0);
row++;
for(int i = 1; i <= col; i++) check(++r0, c0);
col++;
for(int i = 1; i <= row; i++) check(r0, --c0);
row++;
for(int i = 1; i <= col; i++) check(--r0, c0);
col++;
}
return res;
}
}
时间复杂度
O ( m a x ( R , C ) 2 ) O(max(R, C) ^ 2) O(max(R,C)2),遍历所有位置。
空间复杂度
O ( 1 ) O(1) O(1) 使用常数空间额外复杂度。