59. 螺旋矩阵 II

之前研究螺旋矩阵,网上代码绕来绕去很迷惑,下面是一个简单易懂的版本,看完就能直接写出。

题目要求生成一个 n x n 的矩阵,这个矩阵的数字从 1 开始到 n^2 结束,数字按照从外到内顺时针螺旋的方式排列。简单来说,就是让你创建一个正方形的数字阵列,数字从中心向四周螺旋展开,直到填满整个矩阵。

让我们通过一个 4x4 的矩阵来详细解释题目,同时展示变量的变化和矩阵的更新过程。

初始状态

  • n = 4
  • 初始矩阵 matrix = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
  • left = 0, right = 3
  • top = 0, down = 3
  • num = 1

迭代过程与矩阵更新

第一圈填充

  1. 填充顶行 top 从左到右 (leftright)
    • matrix[0][0] = 1, matrix[0][1] = 2, matrix[0][2] = 3, matrix[0][3] = 4
    • top++ -> top = 1
  2. 填充右列 right 从上到下 (topdown)
    • matrix[1][3] = 5, matrix[2][3] = 6, matrix[3][3] = 7
    • right-- -> right = 2
  3. 填充底行 down 从右到左 (rightleft)
    • matrix[3][2] = 8, matrix[3][1] = 9, matrix[3][0] = 10
    • down-- -> down = 2
  4. 填充左列 left 从下到上 (downtop)
    • matrix[2][0] = 11, matrix[1][0] = 12
    • left++ -> left = 1

矩阵现在看起来是这样的:

1  2  3  4
12 0  0  5
11 0  0  6
10 9  8  7

第二圈填充

  1. 填充新的顶行 top 从左到右 (leftright)
    • matrix[1][1] = 13, matrix[1][2] = 14
    • top++ -> top = 2
  2. 填充新的右列 right 从上到下 (topdown)
    • matrix[2][2] = 15
    • right-- -> right = 1
  3. 填充新的底行 down 从右到左 (rightleft)
    • matrix[2][1] = 16
    • down-- -> down = 1

矩阵现在看起来是这样的:

1  2  3  4
12 13 14 5
11 16 15 6
10 9  8  7

由于 left > righttop > down,循环结束,所有的 4x4 矩阵都已经正确填充。

变量变化概览

  • 初始: left = 0, right = 3, top = 0, down = 3, num = 1
  • 第一圈结束后: left = 1, right = 2, top = 1, down = 2
  • 第二圈结束后: left = 2, right = 1, top = 2, down = 1 (此时循环条件不再满足,循环结束)
  • 最终生成的矩阵:
1  2  3  4
12 13 14 5
11 16 15 6
10 9  8  7

结论

这段代码通过控制 leftrighttopdown 四个边界指针,在每一圈的迭代中逐步填充矩阵,最终生成一个按螺旋顺序填充数字的 4x4 矩阵。每完成一圈后,相应地调整这四个指针的值,直到填充完成。

代码

下面的代码挺容易理解的,直接模拟即可。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 创建一个n*n的矩阵,初始值为0
        vector<vector<int>> matrix(n, vector<int>(n , 0));
        
        // 定义四个方向的边界:左、右、上、下
        int left = 0 , right = n - 1;
        int top = 0, down = n - 1;
        
        // 初始数字从1开始
        int num = 1;
        
        // 当左边界不超过右边界,且上边界不超过下边界时,循环继续
        while (left <= right && top <= down) {
            // 从左到右填充上边界的行
            for (int i = left; i <= right; i++) {
                matrix[top][i] = num++; // 填充并将num递增
            }
            top++; // 上边界下移
            
            // 从上到下填充右边界的列
            for (int i = top; i <= down; i++) {
                matrix[i][right] = num++; // 填充并将num递增
            }
            right--; // 右边界左移
            
            // 从右到左填充下边界的行
            for (int i = right; i >= left; i--) {
                matrix[down][i] = num++; // 填充并将num递增
            }
            down--; // 下边界上移
            
            // 从下到上填充左边界的列
            for (int i = down; i >= top; i--) {
                matrix[i][left] = num++; // 填充并将num递增
            }
            left++; // 左边界右移
        }
        
        // 返回填充完成的矩阵
        return matrix;
    }
};

此代码通过不断缩小矩阵的边界(左、右、上、下)来实现螺旋填充。每完成矩阵的一圈(即一层)的填充后,相应地调整边界条件,直到所有数字都被填充到矩阵中。这种方式有效地利用了螺旋路径的模式,确保了填充顺序的正确性和高效性。