【C】两道题(杨辉三角、重塑矩阵)了解纯C的malloc()函数与动态数组

1.关于malloc()函数的简介

看我的另一篇博客C语言笔记:分配内存,malloc与数组

2.题1-力扣118. 杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。
在这里插入图片描述在这里插入图片描述

我们需要使用C语言来创建一个动态的二维数组,使它每行的列数等于它的行数。
首先通过malloc()函数来开辟整个二维数组的空间:

malloc()函数:
malloc函数会返回开辟空间的首地址,加(int *)的目的是让计算机知道,如何去划分这个开辟的空间,因为char、int 、long这些类型的字节大小是不一样的,我们知道了首地址,还要知道是以几个字节为单元。所以,这句话一共开辟了8个字节(某些计算机上),这也是为什么我写sizeof(int),而不是直接写4的原因。
————————————————
引用于https://blog.csdn.net/sinat_29957455/article/details/60883355

int** ret = malloc(sizeof(int*) * numRows);

其中,声明了ret是int* * 型指针,它只能指向int*型的对象。
即,ret中储存的是一个储存单元的地址,该储存单元中储存的数据是另外一个储存单元的地址,另外的这个储存单元储存的是一个数值,可以通过**ret访问。
在这里插入图片描述

malloc()函数返回的是一个无类型指针,需要在前面加上强制类型转换:

int** ret = (int**)malloc(sizeof(int*) * numRows);

现在已经通过malloc()函数分配了numRows个指针类型字节长度空间,但每一块空间内都包含着一个未被开辟子空间,所以我们需要对这些空间再次分配内存:

	for(int i=0; i<numRows; i++)
        ret[i] = (int*)malloc(sizeof(int) * (i + 1));

这样,二维数组就创建好了,并且数组每一行的列数都等于行数。

其中ret[i]可以看作是一个一维数组,这里看一下如何建立一维动态数组
int *num;
num = (int *)malloc(N * sizeof(int));
如此,为num开辟了一个存有N个int型的数组空间。

根据题意的要求,我们需要得出返回的行、列的大小。
其中行的大小为

*returnSize = numRows;

列的大小是储存在一个数组中的,同样,先开辟空间分配内存,再赋值。

*returnColumnSizes = malloc(sizeof(int) * numRows);
for(int i=0; i<numRows; i++)
	(*returnColumnSizes)[i] = i + 1;

这里的*returnColumnSizes可以看作是一个一维数组。

最后,通过数学方法可以计算出题目的答案,即每个数字等于上一行左右两个数字之和,且每行第一个和最后一个数字为1,代码如下:

int** generate(int numRows, int* returnSize, int** returnColumnSizes){
    int** ret = (int*)malloc(sizeof(int*) * numRows);
    *returnSize = numRows;
    *returnColumnSizes = malloc(sizeof(int) * numRows);
    for(int i=0; i<numRows; i++){
        ret[i] = malloc(sizeof(int) * (i + 1));
        (*returnColumnSizes)[i] = i + 1;
        ret[i][0] = ret[i][i] = 1;
        for(int j=1; j<i; j++){
            ret[i][j] = ret[i-1][j-1] + ret[i-1][j];
        }
    }
    return ret;
}

2.题2-力扣566. 重塑矩阵

在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x
c)的新矩阵,但保留其原始数据。

给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。

如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

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

第一种解法:
先将原矩阵的数值存到一维数组里,再重塑为新矩阵。

int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
    int z = 0;
    //定义返回的二维矩阵
    int** ret = (int**)malloc(sizeof(int*) * r);
    //定义用于传递的一维向量
    int* nums = (int*)malloc(sizeof(int) * (r * c));
    //判断是否满足重塑条件,即行*列是否相等
    if(matSize * matColSize[0] == r * c){
   		//为返回的行数赋值,为列数开辟储存空间
        *returnSize = r;
        *returnColumnSizes = (int*)malloc(sizeof(int) * r);
        //将原矩阵按序赋给一维数组
        for(int i=0; i<matSize; i++){
            for(int j=0; j<matColSize[0]; j++){
                nums[z++] = mat[i][j];
            }
        }
        z = 0;
        //将一维数组赋给重塑矩阵
        for(int i=0; i<r; i++){
            (*returnColumnSizes)[i] = c;//每一行的列数都是c
            ret[i] = (int*)malloc(sizeof(int) * c);//为重塑矩阵中的每一行开辟列空间。
            for(int j=0; j<c; j++){
                ret[i][j] = nums[z++];
            }
        }
        return ret;
    }
    //不能重塑,直接返回原矩阵
    else{
        *returnSize = matSize;
        *returnColumnSizes = matColSize;
    }
    return mat;
}

第二种解法:
直接从原矩阵里得到重塑矩阵。
具体的思路可以看《官解》。

int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
    int** ret = (int**)malloc(sizeof(int*) * r);
    if(matSize * matColSize[0] == r * c){
        *returnSize = r;
        *returnColumnSizes = (int*)malloc(sizeof(int) * r);
        for(int i=0; i<r; i++){
            (*returnColumnSizes)[i] = c;
            ret[i] = (int*)malloc(sizeof(int) * c);
        }
        for(int j=0; j<r*c; j++){
            ret[j/c][j%c] = mat[j/(*matColSize)][j%(*matColSize)];
        }
        return ret;
    }
    else{
        *returnSize = matSize;
        *returnColumnSizes = matColSize;
    }
    return mat;
}
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值