【解题笔记】二级指针

1.翻转图像

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

/*
 * 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 **myMalloc(int r, int c, int *returnSize, int **returnColumnSizes){
    int **ret = (int **)malloc(sizeof(int *) * r);//开辟一个r块类型为指针类型的空间
    *returnColumnSizes = (int *)malloc(sizeof(int) * r);//为存放每行列数大小的数据开r块整型类型的空间
    *returnSize = r;//返回数组的行数
    for(int i = 0; i < r; i++){
        ret[i] = (int *)malloc(sizeof(int) * c);//在每一行分配c个数组
        (*returnColumnSizes)[i] = c;//将列数的大小放到数组空间
    }
    return ret;
}
//returnColumnSizes,是一个数组,存放的每一行的列数,要对函数外部的数组内元素做改变,传入数组的地址,第一次解引用找到数组,再一次解引用找到对应的元素
int** flipAndInvertImage(int** image, int imageSize, int* imageColSize, int* returnSize, int** returnColumnSizes){
    int r = imageSize;//数组的行数
    int c = imageColSize[0];//数组的列数
    int i, j;
    int **ret = myMalloc(r, c, returnSize, returnColumnSizes);//分配一个行数为r和列数为c的二维数组
    for(i = 0; i < r; i++){
        for(j = 0; j < c; j++){
            ret[i][j] = 1 - image[i][c - 1 -j];//水平翻转后,数组列的下标之和为c - 1
        }
    }
    return ret;
}

2.转置矩阵 

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

/**
 * 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 **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;
}
int** transpose(int** matrix, int matrixSize, int* matrixColSize, int* returnSize, int** returnColumnSizes){
    int c = matrixSize;//行列互换
    int r = matrixColSize[0];
    int i, j;
    int **ret = myMalloc(r, c, returnSize, returnColumnSizes);//分配新的二维数组空间
    for(i = 0; i < r; i++){
        for(j = 0; j < c; j++){
            ret[i][j] = matrix[j][i];//将第i列的元素赋值到第i行
        }
    }
    return ret;
}
//转置矩阵,矩阵的主队角线不变,其余元素的下标交换
//矩阵的行和列交换
//创建一个新数组时,r为新数组的列,c为新数组的行。

3.重塑矩阵

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

/**
 * 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 **mymalloc(int r, int c, int *returnSize, int **returnColumnSizes){
    int **ret = (int **)malloc(sizeof(int *) * r);
    *returnColumnSizes = (int *)malloc(sizeof(int) * r);
    *returnSize = r;
    for(int i = 0; i < r; i++){
        ret[i] = (int *)malloc(sizeof(int) * c);
        (*returnColumnSizes)[i] = c;
    }
    return ret;
}
int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
    int n = matSize;
    int m = matColSize[0];
    int i, id, j;
    int **ret = mymalloc(r, c, returnSize, returnColumnSizes);
    if(n * m != r * c){//如果要求新的数组的所需的元素和原来不同,则不能重新重塑
        *returnSize = n;
        for(i = 0; i < n; i++){
            (*returnColumnSizes)[i] = m;
        }
        return mat;
    }
     //当可以放下时
    for(i = 0; i < r; i++){
        for(j = 0; j < c; j++){
            id = i * c + j;//id表示当前放的这个元素是第几个
            ret[i][j] = mat[id / m][id % m];//id / m 可以知道是第几行,经历了多少个列;id % m可以知道多少列
        }
    }
    return ret;
}

4.二维网格迁移

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

/**
 * 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** shiftGrid(int** grid, int gridSize, int* gridColSize, int k, int* returnSize, int** returnColumnSizes){
    int m = gridSize, n = gridColSize[0], i, j;
    int *temp = (int *)malloc(sizeof(int) * m);//创建一个数组,用来放最后一列的元素,因为最后一列的元素移动一次后去了下一行
    *returnSize = m;//返回的数组有m行
    *returnColumnSizes = (int *)malloc(sizeof(int) * m);//为返回的每行的列数开辟空间
    for(i = 0; i < m; i++){
        (*returnColumnSizes)[i] = n;//给每行的列数赋值
    }
    while(k--){//一次一次地移动,一共移动k次
        for(i = 0; i < m; i++){
            temp[i] = grid[i][n - 1];//先把最后一列存起来,最后放到第一列
            for(j = n - 1; j > 0;j--){
                grid[i][j] = grid[i][j - 1];           
        }
        }
        grid[0][0] = temp[m - 1];
        for(i = 1; i < m; i++){
            grid[i][0] = temp[i - 1];
        } 
    }
    return grid;
}

5.将一维数组转变为二维数组

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

/**
 * 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 **mymaloc(int r, int c, int *returnSize, int **returnColumnSizes){
     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;
     }
     return ret;
 }
int** construct2DArray(int* original, int originalSize, int m, int n, int* returnSize, int** returnColumnSizes){
    int **ret;
    if(originalSize != m * n){//当不能组成二维时,令returnSize等于0,数组元素为空
        *returnSize = 0;
        return ret;
    }
    ret = mymaloc(m, n, returnSize, returnColumnSizes);//若能,分配空间
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            ret[i][j] = original[i * n + j];//按顺序将他们放入新数组
        }
    }
    return ret;
}

6.图片平滑器

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

/**
 * 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 ave(int **img, int m, int n, int i, int j){
    int sum = 0;
    int cnt = 0;
    sum += img[i][j];
    cnt++;
    if(i - 1 >= 0 && j - 1 >= 0){
        sum += img[i - 1][j - 1];
        cnt++;
    }
    if(i - 1 >= 0 && j + 1 < n){
        sum += img[i - 1][j + 1];
        cnt++;
    }
    if(i - 1 >= 0){
        sum += img[i - 1][j];
        cnt++;
    }
    if(j - 1 >= 0){
        sum += img[i][ j- 1];
        cnt++;
    }
    if(j + 1 < n){
        sum += img[i][j + 1];
        cnt++;
    }
    if(i + 1 < m){
        sum += img[i + 1][j];
        cnt++;
    }
    if(i + 1 < m && j - 1 >= 0){
        sum += img[i + 1][ j - 1];
        cnt++;
    }
    if(i + 1 < m && j + 1 < n){
        sum += img[i + 1][j + 1];
        cnt++;
    }
    return sum / cnt;
}
int **mymalloc(int r, int c, int *returnSize, int **returnColumnSizes){
    int **ret = (int **)malloc(sizeof(int *) * r);
    *returnColumnSizes = (int *)malloc(sizeof(int) * r);
    *returnSize = r;
    for(int i = 0; i < r; i++){
        ret[i] = (int *)malloc(sizeof(int) * c);
        (*returnColumnSizes)[i] = c;
    }
    return ret;
}
int** imageSmoother(int** img, int imgSize, int* imgColSize, int* returnSize, int** returnColumnSizes){
    int m = imgSize;
    int n = imgColSize[0];
    *returnSize = m;
    *returnColumnSizes = (int *)malloc(sizeof(int) * m);
    int **ret = mymalloc(m, n, returnSize, returnColumnSizes);
    for(int i = 0; i < m; i++){
        (*returnColumnSizes)[i] = n;
    }
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            ret[i][j] = ave(img, m, n, i, j);
        }
    }
    return ret;
}
//先创建一个新数组,用来存放平均值
//设置一个函数,计算周围的平均数

7.矩阵区域和

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

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

/**
 * 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 **mymalloc(int r, int c, int *returnSize, int **returnColumnSizes){
    int **ret = (int **)malloc(sizeof(int *) * r);
    *returnColumnSizes = (int *)malloc(sizeof(int) * r);
    *returnSize = r;
    for(int i = 0; i < r; i++){
        ret[i] = (int *)malloc(sizeof(int) * c);
        (*returnColumnSizes)[i] = c;
    }
    return ret;
}
int sum(int **mat, int r, int c, int i, int j, int k){
    int z = j, a = i;
    while(a + k >= r){
        a--;
    }
    while(i - k < 0){
        i++;
    }
    while(j - k < 0){
        j++;
    }
    while(z + k >= c){
        z--;
    }
    int sum = 0;
    for(int m = i - k; m <= a + k; m++){
        for(int n = j - k; n <= z + k; n++){
            sum += mat[m][n];
        }
    }
    return sum;
}
int** matrixBlockSum(int** mat, int matSize, int* matColSize, int k, int* returnSize, int** returnColumnSizes){
    int r = matSize;
    int c = matColSize[0];
    int i, j;
    int **ret = mymalloc(r, c, returnSize, returnColumnSizes);
    for(i = 0; i < r; i++){
        for(j = 0; j < c; j++){
            ret[i][j] = sum(mat, r, c, i, j, k);
        }
    }
    return ret;
}
//求区域和,先设置一个新数组,大小和原来的一样。
//设置一个求区域和的函数,符合变量的条件

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

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

int dist(int r1, int c1, int r2, int c2) {
    return fabs(r1 - r2) + fabs(c1 - c2);
}

int** allCellsDistOrder(int rows, int cols, int rCenter, int cCenter, int* returnSize, int** returnColumnSizes) {
    int maxDist = fmax(rCenter, rows - 1 - rCenter) + fmax(cCenter, cols - 1 - cCenter);
    int* bucket[maxDist + 1][2 * (rows + cols)];
    int bucketSize[maxDist + 1];
    memset(bucketSize, 0, sizeof(bucketSize));
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            int d = dist(i, j, rCenter, cCenter);
            int* tmp = malloc(sizeof(int) * 2);
            tmp[0] = i, tmp[1] = j;
            bucket[d][bucketSize[d]++] = tmp;
        }
    }

    int** ret = malloc(sizeof(int*) * rows * cols);
    *returnColumnSizes = malloc(sizeof(int) * rows * cols);
    for (int i = 0; i < rows * cols; i++) {
        (*returnColumnSizes)[i] = 2;
    }
    *returnSize = 0;
    for (int i = 0; i <= maxDist; i++) {
        for (int j = 0; j < bucketSize[i]; j++) {
            ret[(*returnSize)++] = bucket[i][j];
        }
    }
    return ret;
}
int **mymalloc(int r, int c, int *returnSize, int **returnColumnSizes){
    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;
    }
    return ret;
}
int** allCellsDistOrder(int rows, int cols, int rCenter, int cCenter, int* returnSize, int** returnColumnSizes){
    int ansnum = 1;
    int **ans = mymalloc(10001, 2, returnSize, returnColumnSizes);
    //进行比较,并将下标放进去
    int temp = 1;
    ans[0][0] = rCenter,ans[0][1] = cCenter;
    while(ansnum < rows * cols){
        //ansnum 表示元素的个数
        for(int i = 0;i < temp;i++){
            int k = temp - i;
            //temp横纵最大距离
            //k是指距离中心元素的距离
            if(rCenter - k >=0 && cCenter - i >= 0){
                //同一列,向左移动
                //要寻找于他为对角的元素时,可以将中心位置移动,所需的距离减一
                //向左移动i个,所需距离就变成了k-i
                //假设:将中心的列坐标向左几格,那们距离该中心点行的距离减几格,
                //同时符合条件的点必须在坐标内
                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;
            }
            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++;
    }
    *returnSize = ansnum;
    return ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值