代码星球|数组-螺旋矩阵II-leetcode 59

 1. 题目

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

示例:

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

2. 解题思路

该题目是一个模拟过程。直觉上来说,数值应该是用循环可以表示的,每次递增1,跳出循环的条件是数值到达了n^{2}

同时,数值的填充位置也是需要用循环表示的,这个循环要分解成四个边界条件。循环的判断条件是循环次数,每次递增1,直到循环次数用完,即等于0。

但其实,以上两个过程可以合并,因为可以在填充数字的过程中,计算下一个要填充的数值。不需要先创建一个数组,再将数组的数字按规律填充。

再说填充过程的分解:螺旋形,可以看作是四个数组的结合,四个左闭右开的区间的集合,每个转角都是下一个数组的开始。

3. 代码

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 寻找规律,矩阵可以分解成四个数组。边界缩小并不断循环。
        // 数组填充方式 是在数组范围内填充递增的数字
        // 停止的条件是循环结束。
        vector<vector<int>> mat(n, vector<int>(n, 0));
        int len = n - 1; // 表示边界
        int loop = n/2; //循环次数
        int x = 0; //起点
        int y = 0; //起点
        int count = 1; //填充的数值
        int i,j;
        while (loop--) {

            i = x;
            j = y;
            for (j=y; j<y+len; j++){
                mat[i][j] = count++;
            }
            for (i=x; i<x+len; i++){
                mat[i][j] = count++;
            }
            for (; j>y; j--){
                mat[i][j] = count++;
            }
            for (; i>x; i--){
                mat[i][j] = count++;
            }
            x++;
            y++;
            len -= 2;
        }
        if (n%2) {
            int mid = n/2;
            mat[mid][mid] = count;
            
        }
        return mat;
    }
};

tips

1. 如何表示一个区间

比如左闭右开:[a, b)。

for (int i = a; i < b; i++){
}

或者

int i = a;
while ( i < b) {
i++;
}

同时,如果区间的左右端会有规律的变化,比如长度会减少,起点会递增,正如该题所展示的。可以利用一个更大的循环语句块将这些区间包裹住,在这个循环中去改变区间的端点/长度。

一般只需要两个变量,左区间+长度,或者,左区间+右区间,就能体现出变化。这种区间的变化在“滑动窗口”中也有体现。所以要把握住选取的变量之间的关系,理清楚具体的变化规律——什么时候发生变化+如何发生变化。

2. 这道题中需要注意的一个规律是,当n为奇数时,最后的一层一定只有一个块,这时无法分成四个数组去赋值。因此需要对n进行奇偶判断,一个写法可以积累:

if (n%2) {}
//表示如果是奇数,则

3. 在倒数计数循环时,有一个写法可以积累:

while (loop--) {}
// 表示对循环进行计数,每循环一次减1,直到loop为0,此时所有要求的循环次数都完成。

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值