c语言数据结构剑指offer题


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* printNumbers(int n, int* returnSize)
{
    int nums = 1;
    while(n > 0)
    {
         nums *= 10;
        n--;
    }
    int *ans = (int*)malloc(sizeof(int) * (nums - 1));   
    for(int i = 1;i < nums;i++)
    {
        ans[i - 1] = i;
    }
    * returnSize = nums - 1;
    return ans;
    free(ans);
}

输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。

  1. 这是一个oj题目的解答,但是为什么调用函数用int* printNumbers()呢,这是个指针吗?
  2. int* returnSize,这个为什么要用指针呢,最后 * returnSize = nums - 1;,还要解引用,直接不用指针效果不也是这样吗

1、int* printNumbers()中的int表示返回值类型是指向整数的指针,即返回一个整数数组的首地址。函数名printNumbers表示函数的名称。所以这个函数返回一个整数数组的首地址。
2、int
returnSize是一个指向整数的指针,用于存储返回的整数数组的大小。因为C语言中函数只能返回一个值,所以需要通过指针的方式将数组大小返回给调用者。*returnSize = nums - 1是将nums - 1的值赋给指针所指向的内存空间,即将数组大小返回给调用者。如果不使用指针,那么就需要将数组大小和数组本身一起打包成一个结构体或者使用全局变量来存储数组大小,这样会增加代码的复杂度。

问题1:关于为什么返回值为指针,这是为了将一个数组数据返回,才用指针,如果返回int 那么只能返回一个数据;
问题2:int *returnSize是为了将返回值返回给调用的参数。
如有疑问,可私聊。

这个函数返回值是数组,但是光有数组还不行,主程序还得知道数组长度,returnSize的意思就是返回那个返回的数组的长度。

  1. 当前函数的返回值是指针,这明显是个输出型参数
  2. 解引用是因为它是指针啊,需要类型匹配才能赋值,所以才解引用。C语言是这样的,因为没有引用,所以只能通过指针来修改不同栈帧中的数据
不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    解答:

    该问题要求我们使用C语言打印从1到最大的n位十进制数。其中,考虑到n的范围比较大,需要使用字符串来存储每个数字,同时需要注意大数问题。

    具体的步骤如下: 1. 定义一个数组存储每个数字,数组长度为n+1,为了避免大数溢出,一般长度定义为n+2,第一位为0,最后一位为'\0'表示字符串结束符。 2. 定义一个循环,从第一位开始累加,到最大的n位数为止,每次在数组中存储数字,并输出到控制台上。

    下面是具体的代码实现:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    /**
     * 用于打印从1到最大的n位数
     * @param n 最大的位数
     * @param returnSize 输出数组的大小
     * @return 返回由1到最大的n位数组成的数组
     */
    char **printNumbers(int n, int *returnSize) {
        // 定义数组长度
        int len = pow(10, n) - 1;
    
        // 分配空间定义数组
        char **res = (char**)malloc(sizeof(char*) * len);
        for(int i = 0; i < len; i++) {
            res[i] = (char*)malloc(sizeof(char) * (n+2));
            memset(res[i], '0', n+1); // 初始化为'0'其中第0位为数字0第n+1为结束符'\0'
            res[i][n+1] = '\0'; // 结束符
        }
    
        int carry = 0; // 进位
        for(int k = n; k >= 1; k--) { // 从第1位开始计算
            carry = 0;
            for(int i = 0; i < len; i++) {
                int t = res[i][k] - '0'; // 取出第k位的数据
                t += carry; // 把进位加上
                if(k == n) t++; // 最高位加1
                if(t >= 10) { // 需要进位
                    carry = 1;
                    t -= 10;
                } else {
                    carry = 0;
                }
                res[i][k] = t + '0'; // 更新第k位数据
            }
        }
    
        // 由于是倒序生成的需要翻转一下
        for(int i = 0; i < len/2; i++) {
            char *tmp = res[i];
            res[i] = res[len-1-i];
            res[len-1-i] = tmp;
        }
    
        // 返回结果
        *returnSize = len;
        return res;
    }
    
    int main() {
        int n = 3;
        int returnSize;
        char **res = printNumbers(n, &returnSize);
        for(int i = 0; i < returnSize; i++) {
            printf("%s ", res[i]);
        }
        // 释放空间
        for(int i = 0; i < returnSize; i++) {
            free(res[i]);
        }
        free(res);
        return 0;
    }
    

    其中,使用了进位的方法,从末位开始做加法,如果当前位数字超过10,那么需要进位到高位,持续到最高位结束。

    最后,我们需要注意使用完后释放动态分配的空间。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^