精选算法题——矩阵螺旋输出

Posted 翟天保Steven

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了精选算法题——矩阵螺旋输出相关的知识,希望对你有一定的参考价值。

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

题目描述:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

例如,如果输入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,欢迎评论留言,我会及时更正以免误导他人~

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

以上是关于精选算法题——矩阵螺旋输出的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# LeetCode 腾讯精选练习 50 题:螺旋矩阵

#yyds干货盘点# LeetCode 腾讯精选练习 50 题:螺旋矩阵 II

精选力扣500题 第25题 LeetCode 54. 螺旋矩阵c++ / java 详细题解

1050. 螺旋矩阵(25) pat乙级题

刷题精选:顺时针输出递增数组(螺旋递增升天数组)

刷题精选:顺时针输出递增数组(螺旋递增升天数组)