【Leetcode刷题随笔】59 螺旋矩阵

1. 题目描述

给定一个正整数n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。可结合以下原题链接阅读。
原题链接:59 螺旋矩阵

2. 解题思路

本题为模拟矩阵填充过程,不需要设计算法,只要完成正确的填充过程即可。
首先初始化一个n x n的二维矩阵(涉及到动态内存分配),从矩阵左上角开始往顺时针填充,关键在于填充的转角处不要重复填充,所以对于每条边都要遵循严格的统一规则,可以是左闭右开也可以是左开右闭,关键要统一。过程如下:

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

如此把四条边画好,从外圈往内圈填充即可。 关键要统一填充规则,比如如果n为4,第一步按左闭右闭填充了第一行的四个数,第二步又按左闭右开填充最右列,导致行和列交叉处的顶点被重复填充。或者因为左闭右开填第一行,左开右闭填最后一列,导致转角处被漏填充。

以下统一遵循左闭右开的填充规则实现。

3. C语言实现

int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
    //初始化返回的结果数组的大小
    *returnSize = n; //返回矩阵的行数n
    *returnColumnSizes = (int*)malloc(sizeof(int) * n); //返回矩阵的列数n

    //初始化返回的结果数组ans
    //ans为指向指针的指针,用于存储指向二维数组(矩阵)的每一行的指针。sizeof(int*)即表示一个一维数组(即矩阵的一行)所需要的空间大小,共n行
    int** ans = (int**)malloc(sizeof(int*) * n);
    //为每一行分配内存并初始化列数
    for(int i = 0; i < n; i++){
        ans[i] = (int*)malloc(sizeof(int) * n); //每行分配n个整数的内存大小
        //returnColumnSizes是(int**)类型,*returnColumnSizes是第一次解引用,得到的是指向(int*)的指针,即指向每一行,赋值为n表示每一行都有n列
        (*returnColumnSizes)[i] = n;
    }
    
    //设置每次循环的起始位置,开始为(0,0)表示从左上角开始
    int startX = 0;
    int startY = 0;
    //设置二维数组的中间值,若n为奇数,则需要最后在中间填入数组
    int mid = n / 2;
    //循环圈数,每圈包含上下左右四条边
    int loop = n / 2;
    //偏移数,用于控制每圈的边界
    int offset = 1;
    //当前要添加的元素
    int count = 1;
    
    while(loop){
        int i = startX;
        int j = startY;
        //模拟上侧从左到右
        for(; j < startY + n - offset; j++){
            ans[startX][j] = count++;
        }
        //模拟右侧从上到下
        for(; i < startX + n - offset; i++){
            ans[i][j] = count++;
        }
        //模拟下侧从右到左
        for(; j > startY; j--){
            ans[i][j] = count++;
        }
        //模拟左侧从下到上
        for(; i > startX; i--){
            ans[i][j] = count++;
        }
        //偏移值每次加2
        offset += 2;
        //遍历起始位置每次+1
        startX++;
        startY++;
        loop--;
    }
    //若n为奇数需要单独给矩阵中间赋值
    if(n % 2){
        ans[mid][mid] = count;
    }
    return ans;
}

螺旋填充逻辑:

  1. 上侧从左到右: 从(startX,startY)开始向右填充,直到直到 j < startY + n - offset。(减去offset,是为右开)
  2. 右侧从上到下: 从 (startX, j) 开始,向下填充,直到 i < startX + n - offset。(同上,右开)
  3. 下侧从右到左: 从 (i, j) 开始,向左填充,直到 j > startY。(是大于不是大于等于,同样右开)
  4. 左侧从下到上: 从 (i, j) 开始,向上填充,直到 i > startX。(同上,右开)

更新变量:

  • offset += 2:每完成一圈,偏移量增加2(因为左右和上下各减少一个边界)。
  • startX++ 和 startY++:下一圈的起始位置向内移动。
  • loop–:减少剩余的圈数。

如果 n 是奇数,矩阵的中心位置 (mid, mid) 需要单独填充,值为 count。

示例
假设 n = 3,生成的螺旋矩阵如下:

1 2 3
8 9 4
7 6 5

填充过程:

填充上侧:1 2
填充右侧:3 4
填充下侧:5 6
填充左侧:7 8
填充中心:9

你可能感兴趣的:(leetcode数组篇,Medium,Tag,leetcode,矩阵,算法)