【解题报告】《LeetCode零基础指南》(第九讲) 二级指针

在这里插入图片描述

☘前言☘

今天是九日集训第八天,我会记录一下学习内容和题解,争当课代表0.0.
链接:《LeetCode零基础指南》(第九讲) 二级指针

🧑🏻作者简介:一个从工业设计改行学嵌入式的年轻人
✨联系方式:2201891280(QQ)
全文大约阅读时间: 20min



🎁主要知识点梳理

📝1.二级指针

指针变量也是一种变量,也会占用存储空间,也可以用&获取它的地址。
如果一个指针指向另一个指针,我们就称它位二级指针。

int x = 1;
int *p1 = &x;
int **p2 = &p1;

当然,套娃的思想,三级指针和四级指针也是有的。不过不怎么常用。

int ***p3 = & p2;
int ****p4 = &p3;

🍤2.解引用

在学习一级指针的时候,我们用*进行解引用,变成普通变量,二级指针经过一次解引用,变成一级指针。

🍡3.力扣中的二级指针

在力扣中,选择用c语言进行求解的时候,往往是下面的传参型势,是什么意思呢?

int** func(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
}
参数名变量类型实际含义
matrix二级指针传入矩阵的首地址
matrixSize普通变量传入矩阵的行数
matrixColSize一级指针传入矩阵每行的列数(是每行,所以是数组)
returnSize一级指针返回矩阵的行数,因为需要返回,所以传过来是地址
returnColumnSize二级指针返回矩阵的每行列数,因为需要返回数组,所以是二级指针。

🍧4.内存申请模板

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;
}


🍗课后习题

832. 翻转图像

832. 翻转图像

题目描述

给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。
水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。
反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]。

思路

按照要求进行翻转就好了,但是需要注意的是如果是正中间的元素,直接进行反转就好了。

int** flipAndInvertImage(int** image, int imageSize, int* imageColSize, int* returnSize, int** returnColumnSizes){
    *returnSize = imageSize;
    *returnColumnSizes = imageColSize;
    int n = imageSize,m = *imageColSize;
    //printf("%d %d",imageSize,*imageColSize);
    for (int i = 0; i < n; i++)    
        for(int j = 0; j < (m + 1) / 2; ++j){
            if(j == m/2)    image[i][j] = !image[i][j];
            else{
                image[i][j] = image[i][j] ^ image[i][m - 1 - j];
                image[i][m - 1 - j] =  image[i][j] ^ image[i][m - 1 - j];
                image[i][j] = image[i][j] ^ image[i][m - 1 - j];
                image[i][j] = !image[i][j];
                image[i][m - 1 - j] = !image[i][m - 1 - j];
            }
        }
    return image;
}

867. 转置矩阵

867. 转置矩阵

题目描述

给你一个二维整数数组 matrix, 返回 matrix 的 转置矩阵 。
矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。

思路

直接按照转置的规则就行新数组的填充就好了。

int** transpose(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
    int m = matrixSize,n = *matrixColSize;
    int **ans = malloc(sizeof(int *) * n);
    *returnSize = n;
    *returnColumnSizes = malloc(sizeof(int) * (*returnSize));
    for(int i = 0; i < *matrixColSize; ++i){
        ans[i] = malloc(sizeof(int) * m);
        (*returnColumnSizes)[i] = matrixSize;
    }
    for(int i = 0; i < matrixSize; ++i)
        for(int j = 0;j < *matrixColSize; ++j)
            ans[j][i] = matrix[i][j];

    return ans;
}

566. 重塑矩阵

566. 重塑矩阵

题目描述

在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。
给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数
重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。
如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

思路

先判断元素一样不,不一样直接返回原始数组。一样的话话按照规则进行填充就好了。

int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
    if(r*c != matColSize[0]*matSize){
        *returnSize = matSize;
        (*returnColumnSizes) = malloc(sizeof(int)*matSize);
        for(int i =0;i < matSize;i++)   (*returnColumnSizes)[i] = matColSize[i];
        return mat;
    }
    int **ans = malloc(sizeof(int *) * r);
    (*returnColumnSizes) = malloc(sizeof(int) * r);
    for(int i = 0;i < r;i++)    (*returnColumnSizes)[i] = c;
    int col = 0,num = 0;
    for(int i = 0;i < r;i++)    ans[i] = malloc(sizeof(int)*c);
    for(int i = 0;i < matSize;i++)
        for(int j = 0;j <matColSize[0];j++){
            ans[col][num++] = mat[i][j];
            if(num == c)    col++,num = 0;
            //printf("%d %d",col,num);
        }
    *returnSize = r;
    return ans;
}

2022. 将一维数组转变成二维数组

2022. 将一维数组转变成二维数组

题目描述

给你一个下标从 0 开始的一维整数数组original和两个整数mn 。你需要使用original中 所有 元素创建一个 m 行 n 列的二维数组。
original中下标从0n - 1(都 包含 )的元素构成二维数组的第一行,下标从 n2 * n - 1(都 包含 )的元素构成二维数组的第二行,依此类推。
请你根据上述过程返回一个 m x n 的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。

思路

其实和上面那道题基本上意思是一样的。

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

1260. 二维网格迁移

1260. 二维网格迁移

题目描述

给你一个 m 行 n 列的二维网格 grid 和一个整数 k。你需要将 grid 迁移 k 次。
每次「迁移」操作将会引发下述活动:

  • 位于 grid[i][j] 的元素将会移动到 grid[i][j + 1]。
  • 位于 grid[i][n - 1] 的元素将会移动到 grid[i + 1][0]。
  • 位于 grid[m - 1][n - 1] 的元素将会移动到 grid[0][0]。

请你返回 k 次迁移操作后最终得到的 二维网格。

思路

按照要求一遍一遍的移动就好了。我觉得更好的方式是变成一维的形势,然后再移动后写回。

int** shiftGrid(int** grid, int gridSize, int* gridColSize, int k, int* returnSize, int** returnColumnSizes){
    //处理返回值
    int m = gridSize, n = *gridColSize,temp[m];
    *returnSize = m;
    *returnColumnSizes = malloc(sizeof(int) * m);
    for(int i = 0; i< m; ++i) (*returnColumnSizes)[i] = n;
    while(k--){
        //执行操作
        for(int i = 0; i < m;++i){
            temp[i] = grid[i][n - 1];
            for(int j = n-1; j > 0; --j)
                grid[i][j] = grid[i][j -1];
        }
        grid[0][0] = temp[m-1];
        for(int i = 1; i < m;++i) grid[i][0] = temp[i-1];
    }
    return grid;

}

661. 图片平滑器

661. 图片平滑器

题目描述

包含整数的二维矩阵 M 表示一个图片的灰度。你需要设计一个平滑器来让每一个单元的灰度成为平均灰度 (向下舍入) ,平均灰度的计算是周围的8个单元和它本身的值求平均,如果周围的单元格不足八个,则尽可能多的利用它们。

思路

依次看周围的8个单元是否存在,然后进行计算平均数字就好了。

nt** imageSmoother(int** img, int imgSize, int* imgColSize, int* returnSize, int** returnColumnSizes){
    if(imgSize == 0 || *imgColSize == 0){*returnSize = 0;return NULL;}
    //返回数组空间申请
    int **ans = malloc(sizeof(int *) * imgSize);
    for(int i = 0;i < imgSize;i++)  ans[i] = malloc(sizeof(int) * (*imgColSize));
    (*returnColumnSizes) = malloc(sizeof(int) * imgSize);
    for(int i = 0;i < imgSize;i++)  (*returnColumnSizes)[i] = *imgColSize;
    *returnSize = imgSize;
    //创建二维前缀和
    int temp[imgSize][*imgColSize];
    
    for(int i = 1;i < imgSize;)
    for(int i = 0;i < imgSize ;i++){
        for(int j = 0;j < *imgColSize;j++){
            int temp = img[i][j],tempnum = 1;
            if(i > 0)   temp += img[i-1][j],tempnum++;
            if(j > 0)   temp += img[i][j-1],tempnum++;
            if(i < imgSize - 1)             temp += img[i+1][j],tempnum++;
            if(j < *imgColSize - 1)  temp += img[i][j+1],tempnum++;
            if(i > 0 && j > 0)  temp+=img[i-1][j-1],tempnum++;
            if(i > 0 && j < *imgColSize-1)   temp += img[i-1][j+1],tempnum++;
            if(i < imgSize - 1 && j > 0) temp+=img[i+1][j-1],tempnum++;
            if(i < imgSize - 1 && j < *imgColSize - 1)  temp+= img[i+1][j+1],tempnum++;
            ans[i][j] = temp/tempnum;
        }
    }
    return ans;
}

1314. 矩阵区域和

1314. 矩阵区域和

题目描述

给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:

  • i - k <= r <= i + k,
  • j - k <= c <= j + k 且
  • (r, c) 在矩阵内。

思路

这个可以使用一个叫做二维前缀和的东东,就是temp[i][j]表示从mat[0][0]mat[i][j]这样一个矩阵的和。

int getnum(int (*temp)[100],int m,int n,int mmax,int nmax){
    if(m < 0)   m = -1;
    else if(m > mmax -1) m = mmax - 1;
    if(n < 0) n = -1;
    else if ( n > nmax -1) n = nmax -1;
    if(m < 0 || n < 0)  return 0;
    else return temp[m][n];
}

int** matrixBlockSum(int** mat, int matSize, int* matColSize, int k, int* returnSize, int** returnColumnSizes){
    if(matSize == 0 || *matColSize == 0) {*returnSize = 0;return NULL;}
    //创建前缀和数组
    int temp[matSize][100];
    temp[0][0] = mat[0][0];
    for(int i = 1;i < matSize;i++)  temp[i][0] = temp[i - 1][0] + mat[i][0];
    for(int i = 1;i < *matColSize;i++)  temp[0][i] = temp[0][i - 1] + mat[0][i];
    for(int i = 1;i < matSize;i++)  
        for(int j = 1;j < *matColSize;j++)
            temp[i][j] = temp[i-1][j] + temp[i][j-1] - temp[i-1][j-1] + mat[i][j];
    *returnSize = matSize;
    (*returnColumnSizes) = matColSize;
    //更新所有信息
    for(int i = 0;i < matSize;i++)
        for(int j = 0;j < *matColSize ;j++)
            mat[i][j] = getnum(temp,i+k,j+k,matSize,*matColSize) + getnum(temp,i-k-1,j-k-1,matSize,*matColSize) - getnum(temp,i-k-1,j+k,matSize,*matColSize) - getnum(temp,i+k,j-k-1,matSize,*matColSize);
    return mat;
}

1030. 距离顺序排列矩阵单元格

1030. 距离顺序排列矩阵单元格

题目描述

给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。
另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。
返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)

思路

我就硬算,就从0到最大遍历添加到结果里。

int** allCellsDistOrder(int rows, int cols, int rCenter, int cCenter, int* returnSize, int** returnColumnSizes){
    int** ans = malloc(sizeof(int*) * 10201),ansnum = 1;
    (*returnColumnSizes) = malloc(sizeof(int)*10201);
    for(int i = 0;i < 10201;i++){
        ans[i] = malloc(sizeof(int)*2);
        (*returnColumnSizes)[i] = 2;
    }
    int temp = 1;
    ans[0][0] = rCenter,ans[0][1] = cCenter;
    while(ansnum < rows * cols){
        for(int i = 0;i < temp;i++){
            int k = temp - i;
            if(rCenter - k >=0 && cCenter - i >= 0){ans[ansnum][0] = rCenter - k;ans[ansnum++][1] = cCenter - i;}
            if(rCenter - i >= 0 && cCenter + k < cols){ans[ansnum][0] = rCenter - i;ans[ansnum++][1] = cCenter + k;}
            //printf("%d %d\n",i,k);
            if(rCenter + k < rows && cCenter + i < cols){ans[ansnum][0] = rCenter + k;ans[ansnum++][1] = cCenter + i;}
            if(rCenter + i < rows && cCenter - k >= 0){ans[ansnum][0] = rCenter + i;ans[ansnum++][1] = cCenter - k;}
        }
        temp++;
        //printf("%d ",ansnum);
    }
    *returnSize = ansnum;
    return ans;
}

🍦写在最后

最近被六级支配,可能不在状态,六级结束我要一点点开始补坑了0.0

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

XingleiGao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值