《Leetcode零基础刷题指南》- 二级指针

目录

前言

一、二级指针参数介绍(刷题)

二、内存申请模板

三、翻转图像(传送门)

 四、转置矩阵(传送门)

五、重塑矩阵(传送门)

六、将一维数组转变为二维数组(传送门)

总结


前言

         常见二级指针不再赘述,主要是在力扣中二级指针的应用,难度较大,反复推敲。


一、二级指针参数介绍(刷题)

int** func(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
}
参数名变量类型实际含义
matrix二级指针传入的矩阵首地址
matrixSize普通变量传入的矩阵的行数
matrixColsize—级指针传入矩阵每行的列数(注意是每行,所以是数组)
returnsize—级指针传出矩阵的行数,由于需要作为参数返回,所以用指针取地址
returnColumnSizes二级指针传出矩阵的每行的列数,由于需要作为数组参数返回,所以用二级指针

 returnColumnSizes:

  • 它是一个指向数组的指针,这里数组是行数组
  • *returnColumnSizes是实际的那个数组,并且数组的每个元素是(*returnColumnSizes)[1]代表的是列数
  • return是个前缀,代表它的定位是返回值,而不是函数传参

二、内存申请模板

声明

int **myMalloc(int r, int c, int* returnSize, int** returnColumnSizes);

        其中,返回值代表申请的二维数组(为了方便理解,我们叫矩阵吧)的首地址。r 和c 代表矩阵的行和列,returnSize 是需要返回给调用方的,实际的矩阵的行,我们会在函数内部将它赋值为r,而 returnColumnSizes 也是需要返回给调用方的,只不过需要返回的是一个数组。所以需要用二级指针。

这个函数就可以作为我们的模板函数的,我们接下来来实现一下它:

int **myMalloc(int r, int c, int* returnSize, int** returnColumnSizes) {
    int i;
    int **ret = (int **)malloc( sizeof(int *) * r );        // (1)
    *returnColumnSizes = (int *)malloc( sizeof(int) * r );  // (2)
    *returnSize = r;                                        // (3)
    for(i = 0; i < r; ++i) {
        ret[i] = (int *)malloc( sizeof(int) * c );          // (4)
        (*returnColumnSizes)[i] = c;                        // (5)
    }    
    return ret;
}

(1)申请一个矩阵(二维数组)的内存,行数为,首地址为ret,二维数组的类型为int **,二维数组中每个元素的类型为─级指针,即int *,对应sizeof(int *)这个表达式;

 (2)为这个矩阵的列申请一个数组来记录它每一行的列数,所以这个列数组的长度应该是行数r(第五条解答了),由于需要作为参数返回给调用方,所以这里调用了—次解引用;

(3) *returnSize 是需要返回的矩阵的行数,调用者不知道这个功能返回的矩阵有多少行,需要实现者告诉他,同样调用一次解引用;

(4)申请矩阵每一行的内存空间,每—行的长度为c,即列数;

(5)每一行的列数长度需要作为返回值返回,所以需要先解引用再索引到行号,即给(*returnColumnSizes)进行赋值;

三、翻转图像(传送门)

给定一个 n x n 的二进制矩阵 image ,先 水平 翻转图像,然后 反转 图像并返回 结果 。

水平翻转图片就是将图片的每一行都进行翻转,即逆序。

例如,水平翻转 [1,1,0] 的结果是 [0,1,1]。
反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。

例如,反转 [0,1,1] 的结果是 [1,0,0]。
 

示例 1:

输入:image = [[1,1,0],[1,0,1],[0,0,0]]
输出:[[1,0,0],[0,1,0],[1,1,1]]
解释:首先翻转每一行: [[0,1,1],[1,0,1],[0,0,0]];
     然后反转图片: [[1,0,0],[0,1,0],[1,1,1]]

🔑思路:

        1.套模板申请二维数组空间

        2.水平翻转取反

int **myMalloc(int r, int c, int* returnSize, int** returnColumnSizes) {
    int i;
    int **ret = (int **)malloc( sizeof(int *) * r );       
    *returnColumnSizes = (int *)malloc( sizeof(int) * r );  
    *returnSize = r;                                      
    for(i = 0; i < r; ++i) {
        ret[i] = (int *)malloc( sizeof(int) * c );         
        (*returnColumnSizes)[i] = c;                        
    }    
    return ret;
}
int** flipAndInvertImage(int** image, int imageSize, int* imageColSize, int* returnSize, int** returnColumnSizes){
    int row = imageSize;
    int col = imageColSize[0];
    //申请二维数组空间
    int** ret = myMalloc(row, col, returnSize, returnColumnSizes);
    for(int i = 0; i < row; i++){
        for(int j = 0; j < col; j++){
            //水平翻转后取反
            ret[i][j] = 1-image[i][col - j - 1];
        }
    }
    return ret;
}

 四、转置矩阵(传送门)

给你一个二维整数数组 matrix, 返回 matrix 的 转置矩阵 。

矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。

示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[1,4,7],[2,5,8],[3,6,9]]
示例 2:

输入:matrix = [[1,2,3],[4,5,6]]
输出:[[1,4],[2,5],[3,6]]

🔑思路:

        1.套公式申请二维数组内存

        2.因为是转置,所以交换行和列

 int** myMalloc(int r, int c, int* returnSize, int** returnColumnSizes){
     int ** ret = (int**)malloc(sizeof(int*)*r);
     *returnSize = r;
     *returnColumnSizes = (int*)malloc(sizeof(int)*r);
     for(int i = 0; i < r; i++){
         ret[i] = (int*)malloc(sizeof(int)*c);
         (*returnColumnSizes)[i] = c;
     }
     return ret;
 }
int** transpose(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
    //转置,行列需要交换
    int col = matrixSize;
    int row = matrixColSize[0];
    int** ret = myMalloc(row, col, returnSize, returnColumnSizes);
    for(int i = 0; i < row; ++i) {
        for(int j = 0; j < col; ++j) {
            ret[i][j] = matrix[j][i];                         
        }
    }
    return ret;
}

五、重塑矩阵(传送门)

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

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

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

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

示例 1:


输入:mat = [[1,2],[3,4]], r = 1, c = 4
输出:[[1,2,3,4]]

🔑思路:

        1.套公式申请二维数组内存空间

        2.判断是否重塑

        3.重点注意二维数组转化为一维连续值,再将一维连续数值按顺序散落到n行m列中

 int **myMalloc(int r, int c, int* returnSize, int** returnColumnSizes) {
    int i;
    int **ret = (int **)malloc( sizeof(int *) * r );        
    *returnColumnSizes = (int *)malloc( sizeof(int) * r );  
    *returnSize = r;                                      
    for(i = 0; i < r; ++i) {
        ret[i] = (int *)malloc( sizeof(int) * c );         
        (*returnColumnSizes)[i] = c;                        
    }    
    return ret;
}
int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
    int n = matSize;
    int m = matColSize[0];
    int** ret = myMalloc(r, c, returnSize, returnColumnSizes);
    //无法重塑,返回原数组
    if(n*m != r*c){
        *returnSize = n;
        for(int i = 0; i < n; i++){
             (*returnColumnSizes)[i] = m;
        }
        return mat;
    }
    for(int i = 0; i < r; i++){
        for(int j = 0; i < c; j++){
            //将二维坐标转化成一维连续数值
            int id = i*c+j;
            //再将一维连续数值,按顺序散落到n行m列当中
            ret[i][j] = mat[id/m][id%m];
        }
    }
    return ret;
}

六、将一维数组转变为二维数组(传送门)

给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和  n 。你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组。

original 中下标从 0 到 n - 1 (都 包含 )的元素构成二维数组的第一行,下标从 n 到 2 * n - 1 (都 包含 )的元素构成二维数组的第二行,依此类推。

请你根据上述过程返回一个 m x n 的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。

示例 1:
输入:original = [1,2,3,4], m = 2, n = 2
输出:[[1,2],[3,4]]
解释:

构造出的二维数组应该包含 2 行 2 列。
original 中第一个 n=2 的部分为 [1,2] ,构成二维数组的第一行。
original 中第二个 n=2 的部分为 [3,4] ,构成二维数组的第二行。

🔑思路:

        1.判断原始数组个数和矩阵个数是否一致

        2.按模板申请二维数组空间

        3.一维到二维的映射

 int **myMalloc(int r, int c, int* returnSize, int** returnColumnSizes) {
    int i;
    int **ret = (int **)malloc( sizeof(int *) * r );        
    *returnColumnSizes = (int *)malloc( sizeof(int) * r );  
    *returnSize = r;                                        
    for(i = 0; i < r; ++i) {
        ret[i] = (int *)malloc( sizeof(int) * c );         
        (*returnColumnSizes)[i] = c;                       
    }    
    return ret;
}
int** construct2DArray(int* original, int originalSize, int m, int n, int* returnSize, int** returnColumnSizes){
    int** ret = myMalloc(m, n, returnSize, returnColumnSizes);
    if(originalSize != m*n){
       *returnSize = 0;
       return NULL;
    }
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            ret[i][j] = original[i*n+j];
        }
    }
    return ret;
}


总结

        1.注意五 、 六 一维到二维 , 二维到一维的映射转换。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

penguin_bark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值