螺旋矩阵(“循环不变量“思想+动画演示+代码实现)

题目

在这里插入图片描述

①循环不变量介绍

for、while等,循环体里面的代码是固定的,所以每次循环的逻辑都得尽量统一,这就是循环不变量原则。(下面具体介绍这种思想带来的优点)

1.视频引入(配合解析细节一起看)

螺旋矩阵

2.解析动画里面的细节

以n=5为例,第一圈的遍历只遍历四个元素。
如果第一圈每次都是遍历五个元素,那么就无法保证循环不变量。
理由:

循环里面的代码逻辑是一样的,如果第一行遍历五个元素,后面的代码就没办法连续遍历五个元素了(自己模拟就知道了!顶多只能再插入四个元素)

补充:不坚持循环不变量也能解决问题,例如行的话遍历5个元素,列的话遍历3个元素,也能把矩阵填满一圈。

但是这种分类讨论去处理会导致代码很冗余,而且逻辑也会很复杂。
所以坚持"循环不变量"这个原则是很有用的!

到这里,大家应该可以体会到循环不变量是怎样的一种思想!

②本题细节补充(思路在视频已经展现了)

n其实得分奇偶数。

n为奇数的话使用循环不变量会剩下中间元素没有填充。
n为偶数的话,就刚好填充完矩阵(可以自己以4*4矩阵试验,不过建议等整篇文章系统看完再实验)

得记录绕圈的次数,且得更新落脚点

circle是圈数

刚开始填充的是n-1个元素。经过一圈以后。填充的次数变成了 (n-1-2*circle)次
填充次数<=0停止填充
(也是因为停止填充的时候,n为奇数的矩阵中心还缺一个待填充。所以才分奇偶性)

落脚点更新:
x,y表示当前该填充的坐标

第一圈更新完之后,坐标是(1,0)。
第二圈开始执行时,填充的坐标为(1,1)。此时circle == 1
推导到一般情况就是每一圈结束之后,落脚点更改为:(circle,circle)

一种技巧:数组表示方向(这种技巧在图论的BFS邻接矩阵四个方向也有用到)

可以不使用这种代码,直接在for循环里面依次写四种代码表示(右下左上顺序的填充,不过有点麻烦)
在这里插入图片描述

③代码实现

class Solution
{
	int dir[4][2]{
		{0,1},//右 
		{1,0},//下 
		{0,-1},//左 
		{-1,0}//上 
	};
public:
    vector<vector<int>> generateMatrix(int n)
    {
    	vector<vector<int>>result(n,vector<int>(n));
    	if(n%2==1){ result[n/2][n/2]=n*n;}
    	
    	int circle = 0;//每加一圈,填充数量减少2
		int full = n-1; //每次循环填充的数量
		int num=1;//该填充的数字大小 
		 
    	while(full>0){//full<=0就无法填充了 
			 
			 int x=circle,y=circle;//该填充位置(x,y) 。每次执行一圈都得更新下一圈落脚点
			 //顺时针
			 //循环的方向 -> 右下左上
			for(int i = 0; i<4 ;i++){ //i控制方向 
				for(int j=0 ; j<full ; j++){//j根据次数填充 
				
					result[x][y]=num++;//填充 
					
					//移动当前该填充的位置 
					x+=dir[i][0];
					y+=dir[i][1];
				}
					
			}
			
		circle++;//一次顺时针结束,增加一圈
		full = n-1-2*circle;//填充的数量随圈数发生变化
		}
		return result;
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值