[学习报告]《LeetCode零基础指南》(第8讲)二级指针
一、今日知识点总结
学习内容:https://blog.csdn.net/WhereIsHeroFrom/article/details/120875692
1 二级指针
1.1 二级指针是啥?
首先,他是变量,一个指向指针的指针,通过 & 获取它的地址
指针,是指向某个变量的地址;存储着某个基本数据变量的地址;那么这个指针,有他自己的地址。
二级指针,则是指向某个指针的地址;存储着某个指针的变量的地址
int a =10;
int *p1 = &a;
int **p2 = &p1;
int ***p3 = &p2;//几乎很少用到
//解引用
int *p = *p2;
int b = *p;
1.1 哪些是二级指针
矩阵 | 二维数组
二维数组,实际上是由一个一维数组,该数组每一项的值是一个一维数组的方式形成的。而一维数组变量实际上是指向第一个元素的地址的指针。则二维数组变量则是指向存储着这些指针地址的指针,故为二级指针。
1.2 怎么用?
力扣中会出现如下情况:
int** func(int** matrix,int matrixSize,int * matrixColSize, int* returnSize, int** returnColumnSizes){
}
参数名 | 变量类型 | 实际含义 |
---|---|---|
matrix | 二级指针 | 矩阵(二维数组)首地址 ---- 数组变量是指向数组首地址的指针变量 |
matrixSize | 普通变量 | 矩阵 行数 |
matrixColSize | 一级指针 | 存储每行的列数的数组 --> 矩阵每行的列数 --> 每一行有几个元素 -->是个数组 |
returnSize | 一级指针 | 返回的矩阵(自行申请内存新建的)的行数:作为参数返回,通过指针取地址的方式传入,方法体中通过解引用来赋值 |
returnColumnSizes | 二级指针 | 返回的矩阵,每一行的列数,作为参数返回,所以是通过指针取地址的方式传入,而记录每行的列数是一个数组,所以此处取地址传入时就是二级指针(作为数组返回) |
2 内存申请模板
模板 === 每个题目都可以套用
二维数组的内存申请模板
//大致声明
int **myMalloc(int r, int c,int* returnSize,int** returnColummSizes);
int **myMalloc(int r,int c,int* returnSize,int** retrunColumnSizes){
int i;
int **ret = (int **)malloc(sizeof(int *) *r ); //先创建一个指针类型的数组,长度为行数r
//二维数组的内存,行数为r,首地址为ret,二维数组类型为int **
*returnColumnSizes = (int *)malloc(sizeof(int) * r);//记录每行有多少列的数组也需要初始化
*returnSize = r;//矩阵的行数则为r
for(i = 0;i<r;i++){//找到每一行的首位
ret[i] = (int *)malloc(sizeof(int) * c);//让每一行的首位指向一个int数组的首地址
(*returnColumnSizes)[i] = c;//则每一行的列数为c (先解引用取得数组变量)
}
return ret;
}
3 可以解哪类题目?
题目类型 | 解法 |
---|---|
翻转图像 | 通过内存申请模板获得一个新的二维数组矩阵,遍历新矩阵,每一项 ret[i][j]= 水平翻转后的位置再取反 = 1- img[i][c-1-j] (数组翻转的操作 依次首末位互换) |
转置矩阵 | 转置:主对角线翻转,行索引与列索引互换 ==>ret[i][j] = matrix[j][i] ===> 建立一个「行=原矩阵列,列为原矩阵行」的新矩阵,根据转置公式赋值。 |
重塑矩阵 | 关键思路:将二维坐标转换成一维连续的数值;再将一维连续数值,按序散落到n行m列中 |
一维数组转二维数组 | 关键: ret[i][j] = original[i*n+j]; 二维数组每一项和一维数组的对应关系 == 二维数组下标 求 一维数组下标 |
4 重点知识点:
二、今日解题
832. 翻转图像
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** flipAndInvertImage(int** image, int imageSize, int* imageColSize, int* returnSize, int** returnColumnSizes){
int r = imageSize;
int c = imageColSize[0];
int i,j;
//通过双指针的方式传入了一维数组的变量,解引用得到一维数组首地址
(*returnColumnSizes) = (int *)malloc(sizeof(int)*r);//二维数组每行的列数,是通过一个一维数组来记录的
int **ret = (int **)malloc( sizeof(int *)*r);//创建一个二维数组
for( i = 0; i<r; i++){
//给二维数组的每一行创建一个一维数组,至此,二维数组构建完毕
ret[i] = (int *)malloc(sizeof(int) * c);
//每一行的列数 = c
(*returnColumnSizes)[i] = c;
}
//水平翻转
for(i = 0;i<r;i++){
if(c&1){
ret[i][c/2] = !image[i][c/2];
}
for(j=0;j<c/2;j++){
ret[i][j] = !image[i][c-j-1];
ret[i][c-j-1] = !image[i][j];
}
}
*returnSize = r;
return ret;
}
867. 转置矩阵
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** transpose(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
//注意这里,行和列交互了 ==> n!=m的情况,行列的结构也会交换
int c = matrixSize;
int r = matrixColSize[0];
int i,j;
*returnColumnSizes = (int *)malloc( sizeof(int) * r);
*returnSize = r;
//构建二维数组
int **ret = (int **)malloc( sizeof(int **) * r);
for(i = 0; i<r; i++){
ret[i] = (int *)malloc( sizeof(int) * c);
(*returnColumnSizes)[i] = c;
}
//转置公式 ret[i][j] = matrix[j][i]
for(i = 0;i<r;i++){
for(j=0;j<c;j++){
ret[i][j] = matrix[j][i];
}
}
return ret;
}
566. 重塑矩阵
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
if(matSize * matColSize[0] != r*c){
*returnSize = matSize;
*returnColumnSizes = matColSize;
return mat;
}
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;
}
for(int i = 0;i<matSize;i++){
for(int j=0;j<matColSize[0];j++){
int count = i*matColSize[0]+j;
ret[count/c][count%c] = mat[i][j];
}
}
// int n =matColSize[0];
// for(int i=0;i<r;i++){
// for(int j=0;j<c;j++){
// int id = i*c +j;
// ret[i][j] = mat[id/n][id%n];
// }
// }
return ret;
}
三、今日收获
四、今日疑问
暂无
五、其他参考
用一维数组来表示二维数组
https://www.bilibili.com/s/video/BV1XJ411a7A8
主要助于理解 一维数组和二维数组转换之间的下标关系求解