自用笔记55——memset赋值问题

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

输入: 3
输出: [1,3,3,1]
进阶:

你可以优化你的算法到 O(k) 空间复杂度吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pascals-triangle-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
long long int C(int m,int n)
{
    long long int i=0,com=1,cm=1;
    for(i=0;i<n;i++)
        com = com*(m-i);
    for(i=1;i<=n;i++)
        cm = cm*i;
    com = com/cm;
    return com;
}

int* getRow(int rowIndex, int* returnSize){
    int *zero = (int *)malloc(sizeof(int)*(rowIndex+1));
    zero[0] = 1;
    if(rowIndex == 0)
    {
        *returnSize = 1;
        return zero;
    }
    int i=0,j=0;
    int *array = (int *)malloc(sizeof(int)*(rowIndex+1));
    memset(array,0,(rowIndex+1)*sizeof(int));
    *returnSize = rowIndex+1;
    array[0] = 1;
    array[rowIndex] = 1;
    if(rowIndex <= 27)
        for(i=1;i<=rowIndex/2+1;i++)
        {
                array[i] = C(rowIndex,i);
                array[rowIndex-i] = array[i];
        }
    else
    {
        int *narray = (int *)malloc(sizeof(int)*(rowIndex+1));
        for(i=0;i<rowIndex+1;i++)
            narray[i] = 1;
        for(i=1;i<=27/2+1;i++)
        {
            narray[i] = C(27,i);
            narray[27-i] = narray[i];
        }
        for(i=28;i<=rowIndex;i++)
        {
            for(j=1;j<=i/2+1;j++)
            {
                array[j] = narray[j-1]+narray[j];
                array[i-j] = array[j];
            } 
            for(j=1;j<rowIndex+1;j++)
                narray[j] = array[j];
        }
    }
    return array;
}

这里用了杨辉三角形的部分数学规律,比如某一行的元素个数是行数加1,、某一行关于中间处对称且两头都是1。

最主要的是这里使用了一个性质某一行某一位的数等于其组合数,即第M行第N个数即为C(M,N),利用这个性质我编写了一个计算组合数的函数。

但是有一个问题就是我编写的函数容易出现溢出问题,在rowIndex等于28时就直接溢出无法计算了,我想了两个解决办法:办法一是从计算组合数的函数下手,通过重新优化计算方法,使其不会溢出;办法二是使用杨辉三角另一个规律即第M行第N个数等于第M-1行第N-1个数和第N个数之和。

这里我采用了第二种方法,没有为什么,就是玩儿~(主要是想联系下使用加法解决该问题)

关于标题所说的memset()赋初值问题,我到今天才发现之前用错了,正确的使用格式是:

memset(array,0,(rowIndex+1)*sizeof(int));

第一个变量是数组名,第二个变量是赋值的数,第三个是数组的空间大小。
这里注意的是说是赋初值,但其实是把数组清零,并没法赋其他的初值。如果想把数组全部赋初值为1,那么就会出现这种情况
在这里插入图片描述
原因是memset函数是按照字节赋值的,int 是4个字节所以为0x01010101,就是十进制的16843009。
另外一点需要注意的是第三个变量数组的空间大小,一般是这种形式的

memset(a,0,n*sizeof(type));

所以给数组赋初值除非是清零,不然还是用for循环吧。

看了官方解答后感觉自己想的太复杂了,又或者是想的太简单了。
在这里插入图片描述
直接使用一个二维数组,就避免了反复利用循环和利用新的数组去存储和计算所需值。另外对第i行的数据进行计算时只是用了第i-1行的数据,所以可以对其进行滚动数组处理,即大大起到压缩作用、

int* getRow(int rowIndex, int* returnSize) {
    *returnSize = rowIndex + 1;
    int* pre = malloc(sizeof(int) * (*returnSize));
    memset(pre, 0, sizeof(int) * (*returnSize));
    int* cur = malloc(sizeof(int) * (*returnSize));
    memset(cur, 0, sizeof(int) * (*returnSize));
    for (int i = 0; i <= rowIndex; ++i) {
        cur[0] = cur[i] = 1;
        for (int j = 1; j < i; ++j) {
            cur[j] = pre[j - 1] + pre[j];
        }
        int* tmp = pre;
        pre = cur;
        cur = tmp;
    }
    return pre;
}

在这里插入图片描述

int* getRow(int rowIndex, int* returnSize) {
    *returnSize = rowIndex + 1;
    int* row = malloc(sizeof(int) * (*returnSize));
    memset(row, 0, sizeof(int) * (*returnSize));
    row[0] = 1;
    for (int i = 1; i <= rowIndex; ++i) {
        for (int j = i; j > 0; --j) {
            row[j] += row[j - 1];
        }
    }
    return row;
}

如果使用乘法:
在这里插入图片描述

int* getRow(int rowIndex, int* returnSize) {
    *returnSize = rowIndex + 1;
    int* row = malloc(sizeof(int) * (*returnSize));
    row[0] = 1;
    for (int i = 1; i <= rowIndex; ++i) {
        row[i] = 1LL * row[i - 1] * (rowIndex - i + 1) / i;
    }
    return row;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值