lc59 螺旋矩阵超详细剖析。(c++)

思路

按照要求,设置初始位置为(0,0),然后通过从左往右,从上到下,从右往左,从下到上的模拟方法生成矩阵。

细节

  1. 闭开的原则什么??

    因为要实现4次循环,所以我们要规定区间的闭开原则,否则会因为区间的闭开原则不一致导致漏掉某些数据。这里我们选择左闭又开[x,y)。

  2. 特殊情况有木有??

    对于n为奇数的情况,矩阵中心要单独赋值。矩阵中心的位置为(n/2,n/2).比如n=3。矩阵中心(1,1).

    123
    894
    765

​ 3.怎么根据n判断有几层螺旋圈?

​ 这里我只能列举了,最后发现是有n/2次循环。 (1,0)(2,1)(3,1),(4,2)(5,2)…到最后其实发现,n每逢一个偶数加 一次螺旋圈。!!这不就是等差数列嘛。所以 最后就是n/2啦。

​ 4.每层螺旋圈后,初始位置和每个循环的结束位置怎么更新?

​ 对于起始位置(beginRow,beginCol),会发现他们其实是在斜对角线上。所以进入下一个螺旋圈前分别+1 即可。

​ 对于循环结束位置。这里需要增设一个变量offset,用来控制结束位置更新。那怎么根据n和(beginRow或者 beginCol)更新呢?

​ 因为每次进入下一个圈,访问的数目减少。最后要让结束位置<n+beginRow(or beginCol)-offset即可。那么 offset要做什么变化呢?n每逢一个偶数加一次螺旋圈,假设n=6,则一圈完后其实是n=4的情况。这里可以分 析,由于左闭右开的原则,n=6时,访问5个,进入第二圈(也就是n=4)访问3个,可知,每次访问的数目是 减去2的。所以对于offset来说,每次加2就可以了。因为这里我考虑的是相对情况,考虑绝对情况的话那当然 要加上起始位置的值啦。

如果没听懂,那还是列举吧。每圈结束位置的绝对位置是-1的.n=6时有3圈。

nbeginRowoffset结束位置<x
6015(x的值)
6134(x的值)
6253(x的值)

可以很容易推出offset是每次加2的。

vector<vector<int>>ans(n,vector<int>(n,0));//声明一个n*n的值全为0的二维矩阵。
int beginRow=0,beginCol=0;//row行,Col列;
int loop=n/2;
int mid=n/2;
int count=1;//用来给每个内容块赋值
int i,j;
int offset=1;//初始设为1,第一圈是1
while(loop--){
	i=beginRow;
    j=beginCol;
    //从左往右,因为是横向遍历,所以需要改变j
    for(j=beginCol;j<beginRow+n-offset;j++){
        ans[beginRow][j]=count++;
    }
    //从上往下
    for(i=beginRow;i<beginCol+n-offser;i++){
        ans[i][j]=count++;
    }
    //从右往左
    for(;j>beginCol;j--){
        ans[i][j]=count++;
    }
    //从小往上
    for(;i>beginRow;i--){
        ans[i][j]=count++;
    }
    beginRow++;
    beginCol++;
    
    //
    offset+=2;
    if(n%2){
        ans[mid][mid]=count;
	}
}
return ans;

举一反三(逆时针螺旋)

vector<vector<int>>ans(n,vector<int>(n,0));
	 int beginRow=0,beginCol=0;
	 int loop=n/2;
	 int mid=n/2;
	 int offset=1;
	 int count=1;
	 int i,j;
	 //定义左闭右开 
	 while(loop--){
	 	i=beginRow;
	 	j=beginCol;
	 	//从上到下 
		for(i=beginRow;i<n+beginRow-offset;i++){
			ans[i][beginCol]=count++;
		}
		//从左到右 
		for(j=beginCol;j<n+beginCol-offset;j++){
			ans[i][j]=count++; 
		} 
		//从下到上 
		for(;i>beginRow;i--){
			ans[i][j]=count++;
		}
		//从右到左 
		for(;j>beginCol;j--){
			ans[i][j]=count++;
		}
		beginRow++;
		beginCol++;
		//控制遍历次数 
		offset+=2;
	
	 }
	if(n%2){
		ans[mid][mid]=count;
	}
	return ans; 

运行结果:

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值