螺旋式排列数组

本文介绍了如何使用C语言生成螺旋排列的正方形矩阵。作者分享了从问题理解、解题思路到代码实现的全过程,包括二维数组的动态内存分配和遍历规则。通过示例代码展示了具体实现,并提供了运行结果。强调了二维数组分配的注意事项,以及做算法题时画图辅助理解的重要性。


文章目录

  • 前言
  • 解题思路
  • 上代码
  • 总结


前言

螺旋式排列数组在letcode中属于中等难度的题型,但是对于俺这种道行浅的人再次重新拾起正吃灰的C语言的菜鸟来说确实不容易。其实思路不难,按主要是卡在了二维数组空间的分配问题上,最后调试才将代码修补完整,最后还是想记录一下。


一、什么是螺旋式排列数组?

以上便是(自古文人都是贼!) 

是一种由内向外一圈一圈逐渐递增而形成的一个n行n列的正方形矩阵(二维数组)。


letcode-59

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix (顺带题目描述


二、解题思路

1.   由内向外逐层循环遍历,正方形举证的每条边用一个for循环来遍历;

2.   坚持每条边遍历的规则不变,什么时候行变,什么时候列变,分别用一个变量来对其控制

3.   外层一个for循环来控制转的圈数,内层四个for循环老对四条边进行遍历

4.   遍历的次数为  n/2(原因代码注解给出), 当n为单数时要另外加一个if语句进行判断来讲最后一个元素(最中间那个元素)写入数组当中。

5.    特别特别特别注意这里二维数组空间的分配,不知是否有小伙伴和我一样对二维数组的分配直接简单使用一条malloc来分配就不管了,其实这样是错误的。二维数组与一维数组还是有所区别。二维数组的正确空间分配方法是:先给二维数组整体分配一个空间,然后再在这个整体中对一维数组分配空间;如此才是正确的写法(使用的是二级指针,先分配一维再分配另一维,注意最后要记得free)

给出我自己的草稿(其实重新写画了一遍,hhhh……)


  


 自己有些潦草,将就😊

其实我个人觉得,做这种算法题,如果自己的思路不是很清晰,在纸上自己写一遍,画一下,真的效率会高蛮多,记忆更深刻(个人体会)

代码如下(示例):

#include <stdio.h>
#include <stdlib.h>

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

    Notes:  注意二维数组的分配:

动态分配一个n行,m列的二维数组

先动态分配一维数组
p = (int **)malloc(sizeof(int *) * n);

再分配二维
for (i = 0; i < n; i++) {
    p[i] = (int *)malloc(sizeof(int) * m);
}

*/

int** generateMatrix(int n);
int main()
{
    int n;
    printf("请输入正方形矩阵的阶数 n :  ");
    scanf_s("%d", &n);
    //分配一个二维数组
    int** returnArry = (int**)malloc(sizeof(int*) * n);//先分配一个一维的
    for (int i = 0; i < n; i++) {
        returnArry[i] = (int*)malloc(sizeof(int) * n);//再分配二维
    }
    returnArry = generateMatrix(n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%6d", returnArry[i][j]);
        }
        printf("\n\n");
    }
    free(returnArry);
    system("pause");
    return 0;
}
int** generateMatrix(int n) {
    //分配一个二维数组,作为返回值
    int** returnArry = (int**)malloc(sizeof(int*) * n);
    for (int i = 0; i < n; i++) {
        returnArry[i] = (int*)malloc(sizeof(int) * n);
    }
    int startX = 0, startY = 0;
    int offset = 1;
    int count = 1;
    int i, j;
    for (int k = 0; k < n / 2; k++) {  //转一圈,正方形矩阵左右都会减少一列,宽度-2,总宽为n,故循环n/2次
        for (i = startX; i < n - offset; i++) {     //保证行不变,遍历列
            returnArry[startY][i] = count++;
        }
        for (j = startY; j < n - offset; j++) {    //保证列不变,遍历行
            returnArry[j][i] = count++;
        }
        for (; i > startX; i--) {                 //保证行不变,遍历列(此时的i,j都已经最大,到达矩阵最右下角的位置
            returnArry[j][i] = count++;
        }
        for (; j > startY; j--) {                 //保证列不变,遍历行 
            returnArry[j][i] = count++;
        }    //上一个循环的变量是下一个循环中行或列的不变量,衔接
        startX++;
        startY++;
        offset++;
    }
    if (n % 2 == 1) {        //如果n为单数需要将最后(最中间的元素加到数组中去)
        returnArry[startX][startY] = count;
    }
    return returnArry;
}

给出运行结果图:

 IDE:visual  studio 2019

同样给出letcode题解代码如下(自己的题解):

int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
    *returnSize = n;    //二维数组的元素个数
    *returnColumnSizes = (int*)malloc(sizeof(int) * n);  //多少列
    int** returnArry = (int**)malloc(sizeof(int*) * n);    //返回的二维数组
    for (int i = 0; i < n; i++) {
        returnArry[i] = (int*)malloc(sizeof(int) * n);
        (*returnColumnSizes)[i] = n;
    }
    int startX = 0, startY = 0;
    int offset = 1;
    int count = 1;
    int i, j;
    for (int k = 0; k < n / 2; k++) {
        for (i = startX; i < n - offset; i++) {     //保证行不变,遍历列
            returnArry[startY][i] = count++;
        }
        for (j = startY; j < n - offset; j++) {    //保证列不变,遍历行
            returnArry[j][i] = count++;
        }
        for (; i > startX; i--) {                 //保证行不变,遍历列(此时的i,j都已经最大,到达矩阵最右下角的位置
            returnArry[j][i] = count++;
        }
        for (; j > startY; j--) {                 //保证列不变,遍历行 
            returnArry[j][i] = count++;
        }    //上一个循环的变量是下一个循环中行或列的不变量,衔接
        startX++;
        startY++;
        offset++;
    }
    if (n % 2 == 1) {
        returnArry[startX][startY] = count;
    }
    return returnArry;
} 


总结

题目本身不难,但是就是一写就废,一顿Debug,不过前期也正常,一定要坚持,多写写,多练练,自然就熟能生巧,思路也很更清晰,思维也会更活跃,希望对大家有帮助,欢迎大家提问或指正😁😁😁

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值