题目描述:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如,如果输入4*4的矩阵:
1 2 3 4;5 6 7 8;9 10 11 12;13 14 15 16。
则依次打印出数字:
1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10。
解题思路:
本题为了将矩阵顺时针螺旋输出。如下图所示,对每一圈而言,就是先获取第一行,再拿到最后一列,再拿最后一行,最后拿第一列,确定好对应的位置关系,用4个循环即可实现。考虑到可能会碰上行列不一致的情况,所以圈数要取行数和列数最小值的一半。另外,我发现当矩阵为3行4列时,第2圈只有6和7,此时用常规代码会将6重复获取两次,为了避免该情况发生,用mask作为数据是否获取的位置标识。
测试代码:
#include <iostream> #include <vector> #include <string> using namespace std; #define min(a,b) (a < b ? a : b) vector<int> getSpiralData(vector<vector<int>> inputs); int main() { // 输入矩阵 vector<vector<int>> inputs = { {1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16},{17,18,19,20},{21,22,23,24} }; // 输出输入 cout << "输入:" << endl; for (int i = 0; i < inputs.size(); ++i) { for (int j = 0; j < inputs[0].size(); ++j) { cout << inputs[i][j] << " "; } cout << endl; } // 输出螺旋矩阵 vector<int> output = getSpiralData(inputs); // 输出结果 cout << "输出:" << endl; for (int i = 0; i < output.size(); ++i) { cout << output[i] << " "; } cout << endl; system("pause"); return 0; } // 输出螺旋矩阵 vector<int> getSpiralData(vector<vector<int>> inputs) { // 定义行列数 int row = inputs.size(); int col = inputs[0].size(); // 定义起始点 int startr = 0; int startc = 0; // 定义圈数,offset=0为第一圈 int offset = 0; // 初始化输出 vector<int> outputs; // 初始化掩膜,用来避免数据重复存储 vector<vector<bool>> mask(row,vector<bool>(col,false)); // 当行列不一致时,取最小值/2作为圈数 int turns = (min(row, col) + 1 ) / 2; // 单圈存储 while (turns) { int i = startr; int j = startc; // 顺时针第一行 for (j = startc; j < col - offset; j++) { if (!mask[i][j]) { outputs.push_back(inputs[i][j]); mask[i][j] = true; } } j--; // 顺时针最后一列 for (i = startr + 1; i < row - offset; i++) { if (!mask[i][j]) { outputs.push_back(inputs[i][j]); mask[i][j] = true; } } i--; // 顺时针最后一行 for (j = col - offset - 2; j >= startc; j--) { if (!mask[i][j]) { outputs.push_back(inputs[i][j]); mask[i][j] = true; } } j++; // 顺时针第一列 for (i = row - offset - 2; i > startr; i--) { if (!mask[i][j]) { outputs.push_back(inputs[i][j]); mask[i][j] = true; } } i++; // 圈数步进,下一圈的初始点的x和y值均+1 offset++; startr++; startc++; turns--; } return outputs; }
测试结果:
图1 4*4矩阵结果
图2 6*4矩阵结果
如图1所示,4*4的矩阵按顺时针顺利获取,如图2所示6*4的矩阵也能按顺时针顺利获取。感兴趣的可以用3*4行试试,如果不用mask进行判断,得到的结果如图3所示,最后的6是重复的,这是因为第三个循环中j>=startc导致,但是这个等号也是很有必要的,为此加上mask即可解决该麻烦,正确结果如图4所示。
图3 错误的数据
图4 正确的数据
如果代码有什么需要改进的或者有什么bug,欢迎评论留言,我会及时更正以免误导他人~
如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!