矩阵#中等#螺旋矩阵
矩阵#中等#螺旋矩阵
前文
给你一个m
行n
列的矩阵matrix
,请按照顺时针螺旋顺序,返回矩阵中的所有元素。
1
2
3
4
5
6
7
8
9
10
11
12
示例 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 ]
[5,6 ,7 ,8 ]
[9,10,11,12]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
正文
要点:
- 怎么表示这种顺时针的路径
- 观察很好理解,顺时针即可,让代码理解顺时针
- 顺序是处理第一行 最后一列 最后一行 第一列,然后剩下的矩阵重复这个操作直至没有剩下的矩阵
1
2
3
4
5
6
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
}
};
解法1
通过示例找规律, 示例解释1:
1
2
3
[1,2,3]
[4,5,6]
[7,8,9]]
以行列位置来说,设起始点是第一行第一个元素为[1][1],则依次为
开始行不动,列增加直到列边界
[1][1], [1][2], [1][3]
此时列到达边界继续且列不动行增加
[2][3], [3][3]
此时行达到边界继续且行不动列减少
[3][2], [3][1]
此时列到达边界继续且列不动行减少
[2][1] 注意,这里接下来应该是[1][1],但边界应该是动态改变的,此时应该是行不变,列增加
[2][2]
按照这个规律,可以编写从起始点开始的以螺旋形式遍历矩阵的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int row_begin = 0, row_end = matrix.size() - 1;
int col_begin = 0, col_end = matrix[0].size() - 1;
int x = 0, y = -1;
while(1) {
// cout << x << ", " << y << endl;
// res.push_back(matrix[x][y]);
// 按照顺序规律进行循环
while(y != col_end) {
++y;
res.push_back(matrix[x][y]);
}
++row_begin;
while(x != row_end) {
++x;
res.push_back(matrix[x][y]);
}
--col_end;
if (row_begin > row_end) return res;
if (col_end < col_begin) return res;
while(y != col_begin) {
--y;
res.push_back(matrix[x][y]);
}
++col_begin;
while(x != row_begin) {
--x;
res.push_back(matrix[x][y]);
}
--row_end;
if (col_begin > col_end) return res;
if (row_end < row_begin) return res;
// if (y == col_end) {
// ++x;
// ++row_begin;
// if (row_begin > row_end) return res;
// continue;
// } else {
// ++y;
// continue;
// }
// if (x == row_end) {
// --y;
// --col_end;
// if (col_end < col_begin) return res;
// continue;
// } else {
// ++x;
// continue;
// }
// if (y == col_begin) {
// --x;
// --row_end;
// if (row_end < row_begin) return res;
// continue;
// } else {
// --y;
// continue;
// }
// if (x == row_begin) {
// ++y;
// ++col_begin;
// if (col_begin > col_end) return res;
// continue;
// } else {
// --x;
// continue;
// }
}
return res;
}
};
本代码可以通过所有测试用例,编码即为上述思考过程的实现, 即每次将最外圈遍历完成后,内圈的矩阵重复外圈的遍历过程, 接着每次找出每次外圈的规律即可, 即外圈的遍历都为先递增列,随后达到边界递增行,随后达到边界递减列,最后达到边界递减行, 过程中,在每次递增或递减完成要考虑对应边界需要改变,最后思考结束条件即可。
这里值得注意的是,原先结束条件在每次改变边界时进行:
1
2
3
4
5
6
7
8
9
10
11
12
...
++row_begin;
if (row_begin > row_end) return res;
...
--row_end;
if (col_end < col_begin) return res;
...
++col_begin;
if (col_begin > col_end) return res;
...
--row_end;
if (row_end < row_begin) return res;
发现不能通过测试用例[[2,5],[8,4],[0,-1]]
,这是因为这样写, 对于这个测试用例来说,值为8
的元素不会被遍历到,之前已经结束了, 所以将结束语句的位置调整了一下。
总结:
本题前后思考后觉得,这种问题主要还是要找到规律, 特别在于循环中,代码会按照顺序执行,我们只要找到规律特别是结束条件, 编码中关注当前步规律的编码,先不要去想全局的编码,将当前步编码完成后, 组合起来便是完整的代码,剩下的交给代码按规律顺序执行即可。
本文由作者按照 CC BY 4.0 进行授权