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

作者:翟天保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,欢迎评论留言,我会及时更正以免误导他人~

扫描二维码关注公众号,回复: 13715870 查看本文章

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

猜你喜欢

转载自blog.csdn.net/zhaitianbao/article/details/122820956
今日推荐