代码随想录 Day4 数组 | LC59 螺旋矩阵Ⅱ

六、螺旋矩阵Ⅱ

题目:

力扣59:螺旋矩阵Ⅱ

给你一个正整数 n ,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例1:

输入:n = 3

输出:[[1,2,3],[8,9,4],[7,6,5]]

示例2:

输入:n = 1

输出:[[1]]

提示:

  • 1 <= n <= 20

 

解题思路分析:


易错点:

主要集中在边界处理问题上,每次模拟转圈的时候,边界处理都很容易出错;

错误思路:矩阵的四条边,遍历第一条边的时候把第一个节点处理了,这条边的最后一个节点也处理了,那么就导致遍历第二条边的时候,只能从其第二个节点开始处理,处理到其最后一个节点;遍历第三条边的时候,也要从其第二个节点开始处理,可能保留了该边的最后一个节点不处理,留给最后一条边;这就导致对每个节点的处理规则都不一样;要考虑的边界条件特别多;转着转着就乱了

循环不变量: 这里的循环也要遵循循环不变量原则,要坚持用同一个区间开闭规则来处理每一条边;

左闭右开的时候,遍历第一条边时,只处理第一个节点往后遍历,不包含最后一个节点,把最后一个节点留给下一条边,作为下一条边的起始位置;这样每一条边的遍历规则就统一了

循环应该转几圈?(给一个n,结果是n*n的矩阵)

  • 如果n是偶数,那么转n/2圈;
  • 如果n是奇数,那么转n/2圈后,还留下了中间的位置,我们就进行单独赋值,把最后遍历的一个数给中间位置即可。

 

代码讲解:左闭右开

 //定义一个变量,控制循环次数(转圈次数)

 int loop = 0;

 //定义一个二维数组矩阵,存放1到n^2

 int[][] nums = new int[n][n];

 //由于起始位置每一圈都是要变的,所以定义变量来存放起始位置

 int startx = 0, starty = 0;

 //由于终止位置每一圈也都是要变化的,所以需要定义一个变量来控制终止位置

 int offset = 1;

 //定义一个变量用来填充数字,从1到n^2

 int count = 1;

 // 循环转圈,一般坐标用 (i , j) 表示,i表示行,j表示列

 while(loop++ < n / 2) { //判断完边界后,loop从1开始

    // 遍历第一条边(上面横边从左到右)例如n=4,最后一个位置下标就是3,j<3则最后一个位置就不会被遍历到了

    for(int j = starty; j < n - offset; j++) {

        // startx是固定的,因为是这一圈的起始位置(行数)

        nums[startx][j] = count++; //将count赋给数组固定位置后,再将count+1

    }

    //遍历第二条边(右侧竖边从上到下)正方形,边界条件是一样的

    for(int i = startx; i < n - offset; i++) {

        //这里的j在上面的循环结束后,就已经等于n-offset了,指向了上一条边最后一个元素

        // 遍历第二条边的时候,j的值是不变的,表示列值

        nums[i][j] = count++;

    }

    //遍历第三条边(下面横边从右到左),j已经等于n-offset了,不需要初始化了

    for(; j > starty; j--) {

        nums[i][j] = count++;

    }

    //遍历第四条边(左侧由下到上),i已经等于n-offset了,不需要初始化了

    for(; i > startx; i--) {

        nums[i][j] = count++;

    }

    //这样就已经转完了最外侧的一圈,开始转里面那一圈

    //每转一圈起始位置应该加1,缩小了一圈

    startx++;

    starty++;

    //控制终止位置的offset,每转一圈应该+1,因为往里缩了一圈

    offset++;

 }

//转完以后,还需要判断n是否为奇数

 if(n % 2 == 1) {

//此时startx和starty已经走到了中间的位置

nums[startx][starty] = count;

}

 

总结:


求解本题依然是要坚持循环不变量原则

模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。

例如:按左闭右开原则来填充

这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。

这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。

如果是奇数,最后会单独填充中间那个位置。

这也是坚持了每条边左闭右开的原则。

题解:


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值