给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[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,循环k从0开始(你也可以从1开始,我这里没有想太多),计算此时的子矩阵边界;
2,顺时针遍历矩阵的外边界,此时要注意了,当矩阵只有一行或者只有一列时要特殊处理,我在这里吃了亏,做题目是要考虑特殊状态;
3,定义循环次数,找到每一次循环的规律,每循环一次子矩阵都会缩小一环,循环次数是:
std::min(row_size%2 + int(row_size/2), col_size%2 + int(col_size/2));
具体代码如下:
class Solution { public: vector<int> spiralOrder(vector<vector<int>>& matrix) { vector<int> res; if (matrix.empty()) { return res; } int row_size = matrix.size(); int col_size = matrix.front().size(); if (col_size == 0) { return res; } int iter_num = std::min(row_size%2 + int(row_size/2), col_size%2 + int(col_size/2)); // iter_num = 2; for (int i=0; i<iter_num;i++) { auto tmp_res = getBoundary(matrix, i); res.insert(res.end(), tmp_res.begin(), tmp_res.end()); } return res; } std::vector<int> getBoundary(const vector<vector<int>>& matrix, const int k) { int row_num = matrix.size(); int col_num = matrix.front().size();
//计算边界 int start_col = k; int start_row = k; int end_col = col_num-1-k; int end_row = row_num-1-k;
std::vector<int> res; if (start_col>end_col || start_row>end_row) { return res; } // res.insert(res.end(), matrix[start_row].begin()+start_col,matrix[start_row].begin()+end_col);//上边界 for (int s=start_col; s<=end_col; s++) { //上边界 res.emplace_back(matrix[start_row][s]); } for (int i = start_row+1; i <= end_row; i++) { //右边界 res.emplace_back(matrix[i][end_col]); } for (int j = end_col-1; j >= start_col && start_row!=end_row; j--) { //下边界边界,如果只有一行,下边界不遍历,否则会与上边界重复 res.emplace_back(matrix[end_row][j]); } for (int n=end_row-1; n>=start_row+1 && start_col!=end_col; n--) { //左边界,如果只有一列,左边界不遍历,否则会与右边界重复 res.emplace_back(matrix[n][start_col]); } return res; } };