《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. 翻转图像

  • 题目

给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。

水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/flipping-an-image
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 思路分析

水平翻转 <==> 逆序输出,即将每一行的列元素倒着输出倒新数组中

取反 (0 变成 1,1 变成 0), 用1减去当前数,

  • 源码实现
/**
 * 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. 转置矩阵

  • 题目

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

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

  • 思路分析

将行变成列,列变成行,创建新数组逐个保存数组元素即可

  • 源码实现
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. 重塑矩阵

  • 题目

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

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reshape-the-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 思路分析

注意两点:

  • 不相等输出原始矩阵

  • 行遍历顺序填充

为了实现行遍历和填充数据这两个事件,我们可以利用公式f(x) = row * col + col将二维数组的索引值变成连续的一维数组索引值,通过/%分别取原数组当前的行数和列数,具体推导过程就不细说了。

  • 源码实现
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. 将一维数组转变成二维数组

  • 题目

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-1d-array-into-2d-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 思路分析

利用上题给的转换公式,可以解答本题

  • 源码实现
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. 二维网格迁移

  • 题目

给你一个 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 次迁移操作后最终得到的 二维网格。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shift-2d-grid
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 题目分析

参照一维数组实现右移的思想,然后利用第三题给的索引值转换公式,模拟出一维数组的右移操作

  • 源码实现
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. 图片平滑器

  • 题目

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/image-smoother
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 题目分析

题目的意思是求出当前元素的周围的所有元素的平均值,并将结果赋值给当前元素。我的思路是先找到当前元素,然后遍历周围的元素。遍历的时候注意左边界和右边界,确保数组是在[0, row)[0, col)这两个区间内。

  • 源码实现
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. 矩阵区域和

  • 题目

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/matrix-block-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。。

  • 题目分析

参照上题的思路,只不过这里需要注意的是这里的K的值不一定为1,所以对于边界的处理也有所不同,因为确定K的值的大小,所以也不确定什么时候遇到边界值。我的处理是将对应的判断语句改成循环语句,小于0就加1,大于等于row或col就减1,直到索引值都在该数组内。

  • 源码实现
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. 距离顺序排列矩阵单元格

  • 题目

给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。

另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。

返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/matrix-cells-in-distance-order
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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

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

  • 源码实现
/**
 * 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;
}
参与评论 您还未登录,请先 登录 后发表或查看评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

星狱

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值