[矩阵]螺旋矩阵问题(下)

本文详细解析螺旋矩阵问题,通过坐标系划分四个区域,并给出顺时针和逆时针螺旋矩阵的生成算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接着上篇:

[矩阵]螺旋矩阵问题(上):http://blog.youkuaiyun.com/beyongwang/article/details/52089951

网上看到有一种比较通用易懂的算法(参考:http://www.cnblogs.com/eshizhan/archive/2010/06/01/1749013.html),结合这个思路详细的分析一下螺旋矩阵问题,以及如何灵活的改变螺旋的方向以及排列顺序。

首先观察一下有内到外的顺时针的5*5螺旋矩阵:

如果把该矩阵放入坐标系中,按照二维数组的行列增长方向:X轴右方向增大,Y轴下方向增大。效果如下(每个元素/格子代表一个点,而不是每根线,所以下图是坐标是0到4,X和Y轴各有五个点):

如果以该矩阵的中心点为中心,将矩阵分成四部分观察各部分X,Y的变化,可以发现上面部分是X增加,下面部分是X减少,左面部分是Y减少,右面部分是Y增加:

继续观察两条分割线,可以发现他们实际上是两条直线方程X = 4 - Y和X = Y,而四部分分别满足不同的条件(先不考虑点正好在直线上的情况,稍后会说到),如下:

  1. 一部分:X > Y 并且X < 4 - Y。
  2. 二部分:X > Y 并且X > 4 - Y
  3. 三部分:X < Y 并且X > 4 - Y
  4. 四部分:X < Y 并且X < 4 - Y

继续分析点落在直线方程的情况,看下图,以3,5,7,9四个点为例,对于3点,它的下一步要往左(--X)所以它属于区域三,类似的推断方法,5属于区域四,7属于区域一,9属于区域一,所以考虑点落到线上的情况则四个区域满足的条件为:

  1. 一部分:X >= Y 并且X <= 4 - Y。
  2. 二部分:X > Y 并且X > 4 - Y
  3. 三部分:X <= Y 并且X > 4 - Y
  4. 四部分:X < Y 并且X <= 4 - Y。

分析清楚以上机制就可以写代码了,代码如下,具体参考注释:
vector<vector<int>>  generateSpiralMatrixI(int n) {
	vector<vector<int>> retVec(n, vector<int>(n, 0));

	if (0 == n)//边界条件判断
	{
		return retVec;
	}

	int x = n / 2;
	int y = n / 2;
	for(size_t index = 1; index <= n * n; ++index)//外层循环,负责控制要填充的元素内容
	{
		if (x >= y && x <= n - 1 - y)//元素落入上图区域一中
		{
			retVec[y][x] = index;//元素入座
			++x;//x增加,即向右移动
		}
		else if(x > y && x > n - 1 - y)//元素落入上图区域二中
		{
			retVec[y][x] = index;
			++y;//y增加,即向下移动
		}
		else if (x <= y && x > n - 1 - y)//元素落入上图区域三中
		{
			retVec[y][x] = index;
			--x;//x减少,即向左移动
		}
		else if (x < y && x <= n - 1 - y)//元素落入上图区域四中
		{
			retVec[y][x] = index;
			--y;//y减少,即向上移动
		}
	}
	return retVec;
}


运行结果如下,注意奇数行列数和偶数行数的矩阵由于起始点不一样(偶数行数中心点其实不在中心),所以前几个元素方向不太一样,但是整体的方向是一致的:
了解了以上原理,就可以针对题目的要求,稍微调整代码形成不同方向,不同顺序的螺旋矩阵了,只要判断好在某一个区域中,x和y应该这么变化,尤其要注意当点落在区域分割线上时的情况,要判断好。
例如,要求从外向内逆时针旋转:
可以转化为跟之前的例子一样,从内向外顺时针旋转,只不过从最大元素开始填充位置即可:
vector<vector<int>>  generateSpiralMatrixI(int n) {
	vector<vector<int>> retVec(n, vector<int>(n, 0));

	if (0 == n)
	{
		return retVec;
	}

	int x = n / 2;
	int y = n / 2;
	for(size_t index = n * n; index >= 1; --index)
	{
		...//Same as before:D	
	}
	return retVec;
}


最后,有一点需要注意,一定要按照填充的顺序调整x和y,例如上个例子中,按照顺序依次是向右(x++),向下(y++),向左(x--),向上(y--),那么代码中就要按照这个顺序去写,在改变螺旋方向时,一定要注意这一点。
以上就是关于螺旋矩阵的一点整理。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值