59. 螺旋矩阵 II(C++)

题目

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

示例:

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

分析与题解

本题不涉及算法,只是模拟赋值的过程,十分考验对代码的观察能力。

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

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

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

image-20201230160939283

这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。本质是坚持了每条边左闭右开的原则

完整代码如下:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 初始化为全0数组
        vector<vector<int>> res(n, vector<int>(n, 0));
        // 奇偶的区别在于奇数边界需要单独赋值
        int loop = n / 2;
        int mid = n / 2;
        // 每一圈循环控制边的长度
        int offset = 1;
        // 进行值的计数
        int count = 1;
        int startX = 0, startY = 0;

        while (loop) {

            int i = startX;
            int j = startY;
            // 先进行左上到右上的填充
            for (j = startY; j < startY + n - offset; j++) {
                res[startX][j] = count++;
            }

            // 再进行右上到右下的填充
            // 列j此时退出循环的值正好为边界列
            for (i = startX; i < startX + n - offset; i++) {
                res[i][j] = count++;
            }

            // 再从右下到左下
            for ( ; j > startY; j--) {
                res[i][j] = count++;
            }

            // 再遍历左下到左上
            for ( ; i > startX; i--) {
                res[i][j] = count++;
            }

            // 更新初始点的位置
            startX++;
            startY++;
            loop--;
            // 上下左右各有宽度1的padding
            // 所以每边赋值宽度减少2
            offset += 2;
            
        }

        // 对于奇数,需要额外对中心点进行赋值
        if (n % 2 == 1)
            res[mid][mid] = n * n;

        return res;
    }
};
posted @ 2020-12-30 16:13  脱线森林`  阅读(184)  评论(0编辑  收藏  举报