0.知识概念
- 一维数组名是一级指针,二维数组名是二级指针
int **matrix1;
int matrixSize1;
int matrixColSize1;
int returnSize1;
int **returnColumnSizes;
调用:func(matrix1,matrixSize1,&matrixColSize1,&returnSize1,returnColumnSizes1);
int return_r = returnSize1;
int return_c = (* returnColumnSizes)[j];//j代表第j行
或int return_c = *(*(returnColumnSizes+i)+j);
因为是一维数组,
所以恒有i==0;
所以:int return_c = *(*(returnColumnSizes+0)+j);
即:int return_c = *(*(returnColumnSizes)+j);//return_c为返回矩阵第j行的列数。
等价于int return_c = (* returnColumnSizes)[j];
e.g.
int returnColumnSizes2[n];
func(matrix1,matrixSize1,&matrixColSize1,&returnSize1,&returnColumnSizes2);
/*&returnColumnSizes2==将列类型转变为行类型*/
int** func(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
}
matrix—传入矩阵首地址
matrixSize—传入矩阵行数
matrixColsize–传入矩阵每行的列数
returnSize—传出的参数,要想传出,那就必须得是从外界传入地址,传入地址后
才能同步改变那个变量
returnColumnSizes—传出的参数是一维数组指针,因为这个一维数组里存放着矩阵中每一行的列数
e.g. int returnColumnSizes[n];
int **myMalloc(int r, int c, int *returnSize, int **returnColumnSizes)
{
int i;
int **ret =(int **)malloc(sizeof(int *)*r);/*可以写成int **ret;*/
*returnColumnSizes = (int *)malloc(sizeof(int)*r); //(3)
*returnSize = r;/*传出矩阵的行数*/
for(i = 0; i < r; ++i) {
ret[i] = (int *)malloc( sizeof(int) * c ); /*(4)与(3)等价*/
(*returnColumnSizes)[i] = c; /*(5)一维数组看作是二维数组的第0行*/
}
return ret;
}
}
2. 解题报告
Q1: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 i,j;
int r = imageSize;
int c = *(imageColSize);/*等价于imageColSize[0]*/
/*新的二维数组retImage,新申请了一个空间,这个空间中的值都是指针。所以二维数组名是一个二级指针*/
int **retImage = (int **)malloc(sizeof(int *)*imageSize);//(1)
*returnColumnSizes = (int *)malloc(sizeof(int)*r);//(2)给一维数组开辟空间
/*确定返回行数*/
*returnSize = r;
/*确定返回矩阵每行的列数*/
for(i=0;i<r;++i)
{
/*最本质,指的是二维数组第i个元素的首地址,地址类型是整型,最核心的要求同.
二维数组的每一个元素都是所申请的一维数组空间的首地址(2)*/
*(retImage+i) = (int *)malloc(sizeof(int)*c);//(3)
*((*returnColumnSizes)+i) = c;
}
/*首先翻转每一行*/
for(i=0;i<r;++i)
{
for(j=0;j<c;++j)
{
retImage[i][j] = image[i][c-1-j];
}
}
/*再翻转每一元素*/
for(i=0;i<r;++i)
{
for(j=0;j<c;++j)
{
retImage[i][j] ^= 1;
}
}
return retImage;
}
Q2: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){
int r = matrixSize;
int c = *(matrixColSize);
int i,j;
/*返回行数*/
*returnSize = c;
/*返回列数存在一个一维数组中,这个一维数组有c个整型元素,
一维数组指针指向一维数组,一维数组指针的基类型是一维数组,
二维数组的元素,是一维数组,用一维数组名表达,一维数组名是列元素地址。
所以用列元素地址表达。
*/
*returnColumnSizes = (int *)malloc(sizeof(int)*c);/*给一维数组申请空间*/
/*申请新的二维矩阵空间*/
int **retMatrix =(int **)malloc(sizeof(int *)*c);
for(i=0;i<c;++i)
{
/*给二维数组(二维矩阵)的每一个元素赋值,该值是一维整型数组的的首地址*/
*(retMatrix+i) = (int *)malloc(sizeof(int)*r);
/*给一维数组元素赋值*/
*((*returnColumnSizes)+i) = r;
}
/*------------------------------------------------------------------*/
for(i = 0;i<r;++i)
{
for(j = 0;j<c;++j)
{
retMatrix[j][i] = matrix[i][j];
}
}
return retMatrix;
}
Q3:566. 重塑矩阵
/*内存申请模板*/
int **myMalloc(int r, int c, int* returnSize, int** returnColumnSizes)
{
int i;
/*返回新二维数组的行数*/
*returnSize = r;
/*准备一个一维数组空间,来存每一行的列数*/
*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);
*((*returnColumnSizes)+i) = c;
}
return ret;
}
/**
* 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){
int ** ans;
ans = myMalloc(r,c,returnSize,returnColumnSizes);
int mr = matSize;
int mc = *(matColSize);
int i,j,id;
if(mr*mc != r*c)
{
/*返回行参数*/
*returnSize = mr;
/*返回列参数,确定每行的列数为mc*/
for(i=0;i<mr;++i)
{
(*returnColumnSizes)[i] = mc;
}
/*返回原矩阵,本函数结束*/
return mat;
}
for(i=0;i<r;++i)
{
for(j=0;j<c;++j)
{
id = i*c + j;
ans[i][j] = mat[id/mc][id%mc];/*注意运算逻辑*/
}
}
return ans;
}
}
Q4:2022. 将一维数组转变成二维数组
int **myMatrix(int r,int c,int *returnSize,int **returnColumnSizes)
{
*returnSize = r;
*returnColumnSizes = (int *)malloc(sizeof(int)*r);
int i ;
int** ans =(int **)malloc(sizeof(int*)*r);
for(i=0;i<r;++i)
{
*(ans + i) = (int *)malloc(sizeof(int)*c);/*给二维数组赋值*/
*((*returnColumnSizes)+i) = c; /*给一维数组赋值*/
}
return ans;
}
/**
* 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** construct2DArray(int* original, int originalSize, int m, int n, int* returnSize, int** returnColumnSizes){
int **ret;
int i,j;
/*无法构成这样的二维数组*/
if(originalSize != m*n)
{
*returnSize = 0;
//int **returnColumnSizes;默认为NULL
return ret;/*ret == NULL*/
}
int r = m;
int c = n;
ret = myMatrix(r,c,returnSize,returnColumnSizes);
for(i=0;i<r;++i)
{
for(j=0;j<c;++j)
{
ret[i][j] = original[i*c+j];
}
}
return ret;
}
3.思考总结
(1)
int **ret =(int **)malloc(sizeof(int *)*r);
不只是给二级指针初始化赋值,
为了满足指针变量有实参?这一句省略等号右侧会报错吗?——等号右侧不可省略,ret的值参与到了给二维数组元素赋值的运算,偏移一个数组字节的大小。
开辟r个整型变量的地址空间
int (* ret)[r];
这个效果类似于静态分配,直接定义一个二维数组 int ret[r][c];
(2)
for(i = 0; i < r; ++i) {
ret[i] = (int *)malloc( sizeof(int) * c ); // (4)
(*returnColumnSizes)[i] = c; // (5)
}
ret的值在for循环中,被替代了吗?
没有,在for循环中,ret[i]—代表二维数组第i个元素值,这个元素是一个一维数组名,代表地址。