# 《LeetCode零基础指南》(第九讲) 二级指针

## 二级指针返回函数模板

int **my_Malloc(int row, int col, int *returnSize, int **returnColumnSizes)
{
int i;
int **ret = (int **)malloc(sizeof(int *) * row); //创建二级指针并初始化
//为这个矩阵的列申请一个数组来记录它每一行的列数，所以这个列数组的长度应该是行数r
*returnColumnSizes = (int *)malloc(sizeof(int) * row);
*returnSize = row;  //返回每一列中的行数
for(i = 0; i < row; ++i)
{
ret[i] = (int *)malloc(sizeof(int) * col);  //每一行的长度
(*returnColumnSizes)[i] = col;  //返回每一行的长度，即列数
}
return ret;
}


### 1. 翻转图像

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 row = imageSize;
int col = imageColSize[0];
int **ret = my_Malloc(row, col, returnSize, returnColumnSizes);

for(i = 0; i < row; ++i)
{
for(j = 0; j < col; ++j)
{
ret[i][j] = 1 - image[i][col - 1 - j]; //水平翻转后取反
}
}
return ret;
}


### 2. 转置矩阵

867. 转置矩阵

• 题目

• 思路分析

• 源码实现
int** transpose(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
int i, j;
int col = matrixSize;	//将行变成列，列变成行
int row = matrixColSize[0];
int **ret = my_Malloc( row, col, returnSize, returnColumnSizes);

for(i = 0; i < row; ++i)
{
for(j = 0; j < col; ++j)
{
ret[i][j] = matrix[j][i]; //行列互换实现转置操作
}
}

return ret;
}


### 3.重塑矩阵

566. 重塑矩阵

• 题目

• 思路分析

• 不相等输出原始矩阵

• 行遍历顺序填充

• 源码实现
int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
int i, j;
int id = 0;
int row = matSize;
int col = matColSize[0];

int **ret = my_Malloc(r , c, returnSize, returnColumnSizes);
if(row * col != r * c)	//不相等直接返回
{
*returnSize = row;	//返回数组的行数
for(i = 0; i < row; ++i)
{
(*returnColumnSizes)[i] = col; //每一行的列数
}
return mat;
}

for(i = 0; i < r; ++i)
{
for(j = 0; j < c; ++j)
{
id = i * c + j;   //将二维数组的索引值变成连续一维数组的索引值
ret[i][j] = mat[id / col][id % col]; //除号获取当前行数，取余获取当前列数
}
}

return ret;
}


### 4. 将一维数组转变成二维数组

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

• 题目

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

• 思路分析

• 源码实现
int** construct2DArray(int* original, int originalSize, int m, int n, int* returnSize, int** returnColumnSizes){
int i, j;
int **ret = my_Malloc(m, n, returnSize, returnColumnSizes);

if(m * n != originalSize) //二维数组的大小与原数组大小不等返回空数组
{
*returnSize = 0;
return ret;
}

for(i = 0; i < m; ++i)
{
for(j = 0; j < n; ++j)
{
ret[i][j] = original[i * n + j];	//将原数组假定m * n 数组，按照转换公式依次赋值
}
}

return ret;
}


### 5. 二维网格迁移

1260. 二维网格迁移

• 题目

• 位于 grid[i][j] 的元素将会移动到 grid[i][j + 1]

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

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

• 题目分析

• 源码实现
int** shiftGrid(int** grid, int gridSize, int* gridColSize, int k, int* returnSize, int** returnColumnSizes){
int i, j;
int id;
int row = gridSize;
int col = gridColSize[0];

int **ret = my_Malloc(row, col, returnSize, returnColumnSizes);
for(i = 0; i < row; ++i)
{
for(j = 0; j < col; ++j)
{
id = (k + i * col + j) % (row * col);	 //模拟一维数组的右移，从第k位置开始赋值
ret[id / col][id % col] = grid[i][j];	//从新数组的第K位开始插入
}
}

return ret;
}


### 6. 图片平滑器

661. 图片平滑器

• 题目

• 题目分析

• 源码实现
int averageGrayscale(int **img, int ir, int ic, int max_ir, int max_ic)
{
int i = ir - 1;	//当前位置的左上半边
int j = ic - 1;
int row = ir + 1;	//当前位置的右下半边
int col = ic + 1;
int sum = 0;
int cnt = 0;    //统计计算次数
if(i < 0)  //处理上边界
{
i = ir;
}
if(j < 0)  //处理左边界
{
j = ic;
}
if(row >= max_ir) //处理下边界
{
row = ir;
}
if(col >= max_ic)    //处理右边界
{
col = ic;
}
int tmp = j;    //每次循环结束后要还原j的值
for(i; i <= row; ++i)   //统计所有值的和
{
j = tmp;
for(j; j <= col; ++j)
{
sum += img[i][j];
++cnt;
}
}
return sum / cnt;   //返回平均值的结果
}
int** imageSmoother(int** img, int imgSize, int* imgColSize, int* returnSize, int** returnColumnSizes){
int i, j;
int row = imgSize;
int col = imgColSize[0];
int sum = 0;
int **ret = my_Malloc(row, col, returnSize, returnColumnSizes);

for(i = 0; i < row; ++i)
{
for(j = 0; j < col; ++j)
{
sum = averageGrayscale(img, i, j, row, col);
ret[i][j] = sum; //结果赋值到新数组
}
}
return ret;
}


### 7. 矩阵区域和

1314. 矩阵区域和

• 题目

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

• 题目分析

• 源码实现
int answer(int **mat, int mr, int mc, int k, int max_mr, int max_mc)
{
int i = mr - k;
int j = mc - k;
int row = mr + k;
int col = mc + k;
int sum = 0;
while(i < 0)    //上边界
{
++i;
}
while(j < 0)    //左边界
{
++j;
}
while(row >= max_mr)    //下边界
{
--row;
}
while(col >= max_mc)    //右边界
{
--col;
}

int tmp = j;    //临时变量保存j的值
for(i; i <= row; ++i)
{
j = tmp;
for(j; j <= col; ++j)
{
sum += mat[i][j];
}
}

return sum;
}
int** matrixBlockSum(int** mat, int matSize, int* matColSize, int k, int* returnSize, int** returnColumnSizes){
int i, j;
int row = matSize;
int col = matColSize[0];
int sum = 0;

int **ret = my_Malloc(row, col, returnSize, returnColumnSizes);
for(i = 0; i < row; ++i)
{
for(j = 0; j < col; ++j)
{
sum = answer(mat, i, j, k, row, col);
ret[i][j] = sum; //得到的总和写入数组
}
}

return ret;
}


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

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

• 题目

• 题目分析
• 这题我自己的想法是按照几何法来获取求解，即先算元素周边的上下左右的四个元素，以正方形的形式向外扩张，得到的结果一定是从小到大的。但思路虽有，代码却写不出来，最终是参照了官方的思路。

• 官方的思路是直接排序，首先先将对应的坐标位置赋值到新数组，其次使用内置函数进行排序

• 源码实现
/**
* 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 r0, c0;
int cmp(const void *_a, const void *_b)
{
int *a = *(int **)_a;	//索引到数组ret[i][j]，并取出地址中的保存的内容
int *b = *(int **)_b;
//返回某一行中的列元素相加之后减去下一行列元素相加之后的结果，谁大谁往右移
return abs(a[0] - r0) + abs(a[1] - c0) - abs(b[0] - r0) - abs(b[1] - c0);
}

int** allCellsDistOrder(int rows, int cols, int rCenter, int cCenter, int* returnSize, int** returnColumnSizes){
r0 = rCenter;
c0 = cCenter;
int i, j;
int row = rows * cols;
int col = 2;
int **ret = my_Malloc(row, col, returnSize, returnColumnSizes);

*returnSize = 0;
for(i = 0; i < rows; ++i)
{
for(j = 0; j < cols; ++j)
{
ret[*returnSize][0] = i;	 //对应[i][0]位置
ret[*returnSize][1] = j;	//对应[i][1]位置
(*returnSize)++; //每次遍历完大小加1
}
}
qsort(ret, row, sizeof(int *), cmp);
return ret;
}

10-20 4823

04-10 60
03-21 49
10-20 7766
12-17 559

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

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

¥2 ¥4 ¥6 ¥10 ¥20

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