【学习报告】《LeetCode零基础指南》(第八讲) 二级指针
目录
一、练习题目
832. 翻转图像
867. 转置矩阵
566. 重塑矩阵
2022. 将一维数组转变成二维数组
1260. 二维网格迁移
661. 图片平滑器
1314. 矩阵区域和
1030. 距离顺序排列矩阵单元格
二、答题总结
一、练习题目
832. 翻转图像
给定一个 n x n 的二进制矩阵 image ,先 水平 翻转图像,然后 反转 图像并返回 结果 。
水平翻转图片就是将图片的每一行都进行翻转,即逆序。
例如,水平翻转 [1,1,0] 的结果是 [0,1,1]。
反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0,1,1] 的结果是 [1,0,0]。
示例 1:
输入:image = [[1,1,0],[1,0,1],[0,0,0]]
输出:[[1,0,0],[0,1,0],[1,1,1]]
解释:首先翻转每一行: [[0,1,1],[1,0,1],[0,0,0]];
然后反转图片: [[1,0,0],[0,1,0],[1,1,1]]
示例 2:输入:image = [[1,1,0,0],[1,0,0,1],[0,1,1,1],[1,0,1,0]]
输出:[[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]
解释:首先翻转每一行: [[0,0,1,1],[1,0,0,1],[1,1,1,0],[0,1,0,1]];
然后反转图片: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]
class Solution { public int[][] flipAndInvertImage(int[][] image) { int n=image.length; int m=image[0].length; int[][] arr=new int[n][m]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ arr[i][m-j-1]=image[i][j]; } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(arr[i][j]==1){ arr[i][j]=0; }else{ arr[i][j]=1; } } } return arr; }}
867. 转置矩阵
给你一个二维整数数组 matrix, 返回 matrix 的 转置矩阵 。
矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[1,4,7],[2,5,8],[3,6,9]]
示例 2:输入:matrix = [[1,2,3],[4,5,6]]
输出:[[1,4],[2,5],[3,6]]
class Solution { public int[][] transpose(int[][] matrix) { int m = matrix.length; int n = matrix[0].length; int[][] res = new int[n][m]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { res[j][i] = matrix[i][j]; } } return res; }}
566. 重塑矩阵
在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。
给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。
如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。
示例 1:
输入:mat = [[1,2],[3,4]], r = 1, c = 4
输出:[[1,2,3,4]]
示例 2:
输入:mat = [[1,2],[3,4]], r = 2, c = 4
输出:[[1,2],[3,4]]
class Solution { public int[][] matrixReshape(int[][] mat, int r, int c) { int m = mat.length, n = mat[0].length; // 特殊情况判断 if (m * n != r * c) { return mat; } // 双重循环 + 数组元素位置 // 例:原5*7数组中的一个元素a[2][4],要放在新的7*5数组的什么位置?? // a[2][4] = 2 * 7 + 4 = 18 // 按行遍历的话 // 所以他应该在新数组的中得位置:b[18 / 5]][18 % 5] = b[3][3] => 3*5+3=18 int[][] arr = new int[r][c]; int count = 0;// 表示按行遍历时,在数组中的第几个位置 for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { arr[i][j] = mat[count / n][count % n]; count++; } } return arr; }}
-
这个题看的题解,还没有看懂,备注一下,有时间回来再看看。
2022. 将一维数组转变成二维数组
给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和 n 。你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组。
original 中下标从 0 到 n - 1 (都 包含 )的元素构成二维数组的第一行,下标从 n 到 2 * n - 1 (都 包含 )的元素构成二维数组的第二行,依此类推。
请你根据上述过程返回一个 m x n 的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。
示例 1:
输入:original = [1,2,3,4], m = 2, n = 2
输出:[[1,2],[3,4]]
解释:
构造出的二维数组应该包含 2 行 2 列。
original 中第一个 n=2 的部分为 [1,2] ,构成二维数组的第一行。
original 中第二个 n=2 的部分为 [3,4] ,构成二维数组的第二行。
示例 2:输入:original = [1,2,3], m = 1, n = 3
输出:[[1,2,3]]
解释:
构造出的二维数组应该包含 1 行 3 列。
将 original 中所有三个元素放入第一行中,构成要求的二维数组。
示例 3:输入:original = [1,2], m = 1, n = 1
输出:[]
解释:
original 中有 2 个元素。
无法将 2 个元素放入到一个 1x1 的二维数组中,所以返回一个空的二维数组。
示例 4:输入:original = [3], m = 1, n = 2
输出:[]
解释:
original 中只有 1 个元素。
无法将 1 个元素放满一个 1x2 的二维数组,所以返回一个空的二维数组。
class Solution { public int[][] construct2DArray(int[] original, int m, int n) { int num=original.length; int k=0; int[][] arr=new int[m][n]; if((m*n)==num){ for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ arr[i][j]=original[k]; k++; } } return arr; } return new int[][]{}; }}
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 次迁移操作后最终得到的 二维网格。示例 1:
输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出:[[9,1,2],[3,4,5],[6,7,8]]
示例 2:输入:grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
输出:[[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]
示例 3:输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
输出:[[1,2,3],[4,5,6],[7,8,9]]
class Solution { public List<List> shiftGrid(int[][] grid, int k) { List<List> ans = new ArrayList<List>(); int n = grid.length; int m = grid[0].length; k = k % (n * m); int begin = n * m - k; for (int i = 0; i < n; i++) { List tmp = new ArrayList(); for (int j = 0; j < m; j++) { int now = (begin + i * m + j) % (n * m); int value = grid[now / m][now % m]; tmp.add(value); } ans.add(tmp); } return ans; }}
661. 图片平滑器
图像平滑器 是大小为 3 x 3 的过滤器,用于对图像的每个单元格平滑处理,平滑处理后单元格的值为该单元格的平均灰度。
每个单元格的 平均灰度 定义为:该单元格自身及其周围的 8 个单元格的平均值,结果需向下取整。(即,需要计算蓝色平滑器中 9 个单元格的平均值)。
如果一个单元格周围存在单元格缺失的情况,则计算平均灰度时不考虑缺失的单元格(即,需要计算红色平滑器中 4 个单元格的平均值)。
给你一个表示图像灰度的 m x n 整数矩阵 img ,返回对图像的每个单元格平滑处理后的图像 。
示例 1:
输入:img = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[0, 0, 0],[0, 0, 0], [0, 0, 0]]
解释:
对于点 (0,0), (0,2), (2,0), (2,2): 平均(3/4) = 平均(0.75) = 0
对于点 (0,1), (1,0), (1,2), (2,1): 平均(5/6) = 平均(0.83333333) = 0
对于点 (1,1): 平均(8/9) = 平均(0.88888889) = 0
示例 2:
输入: img = [[100,200,100],[200,50,200],[100,200,100]]
输出: [[137,141,137],[141,138,141],[137,141,137]]
解释:
对于点 (0,0), (0,2), (2,0), (2,2): floor((100+200+200+50)/4) = floor(137.5) = 137
对于点 (0,1), (1,0), (1,2), (2,1): floor((200+200+50+200+100+100)/6) = floor(141.666667) = 141
对于点 (1,1): floor((50+200+200+200+200+100+100+100+100)/9) = floor(138.888889) = 138
class Solution { public int[][] imageSmoother(int[][] img) { int R = img.length, C = img[0].length; int[][] ans = new int[R][C]; for (int r = 0; r < R; ++r) //原数组行遍历 for (int c = 0; c < C; ++c) { //原数组列遍历 int count = 0; //存下周围数的个数 for (int nr = r-1; nr <= r+1; ++nr) //遍历r的上下 for (int nc = c-1; nc <= c+1; ++nc) { //遍历c的左右 if (0 <= nr && nr < R && 0 <= nc && nc < C) { //判断边界ans[r][c] += img[nr][nc]; //将周围数相加count++; //周围有几个个数 } } ans[r][c] /= count; //求平均值 } return ans; }}
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) 在矩阵内。示例 1:
输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出:[[12,21,16],[27,45,33],[24,39,28]]
示例 2:输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2
输出:[[45,45,45],[45,45,45],[45,45,45]]
class Solution { public int[][] matrixBlockSum(int[][] mat, int k) { int n=mat.length; int m=mat[0].length; int[][] arr=new int[n][m]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ for(int k1=i-k;k1<=i+k;k1++){ for(int l=j-k;l<=j+k;l++){ if(k1=0 && l=0){arr[i][j]+=mat[k1][l]; } } } } } return arr; }}
1030. 距离顺序排列矩阵单元格
给定四个整数 row , cols , rCenter 和 cCenter 。有一个 rows x cols 的矩阵,你在单元格上的坐标是 (rCenter, cCenter) 。
返回矩阵中的所有单元格的坐标,并按与 (rCenter, cCenter) 的 距离 从最小到最大的顺序排。你可以按 任何 满足此条件的顺序返回答案。
单元格(r1, c1) 和 (r2, c2) 之间的距离为|r1 - r2| + |c1 - c2|。
示例 1:
输入:rows = 1, cols = 2, rCenter = 0, cCenter = 0
输出:[[0,0],[0,1]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1]
示例 2:输入:rows = 2, cols = 2, rCenter = 0, cCenter = 1
输出:[[0,1],[0,0],[1,1],[1,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2]
[[0,1],[1,1],[0,0],[1,0]] 也会被视作正确答案。
示例 3:输入:rows = 2, cols = 3, rCenter = 1, cCenter = 2
输出:[[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2,2,3]
其他满足题目要求的答案也会被视为正确,例如 [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]]。
class Solution { public int[][] allCellsDistOrder(int R, int C, int r0, int c0) { // 找到最大可达的距离。 int maxDist = Math.max(r0, R-1-r0) + Math.max(c0, C-1-c0); // 创建桶 List<List> bucket = new ArrayList<List>(); // 赋给桶的大小,最大为距离最大,距离一样的放在一个桶。 for(int i=0; i<=maxDist; i++){ bucket.add(new ArrayList()); } //调用方法计算出距离,然后把坐标放在对应的桶中。 for(int i=0; i<R; i++){ for(int j=0; j<C; j++){ int d = dist(i, j, r0, c0); bucket.get(d).add(new int[]{i,j}); } } //创建二维数组对象 int[][] ret = new int[R*C][]; //创建指针 int index = 0; //出桶,加入二维数组中 for(int i=0; i<=maxDist; i++){ for(int j=0; j<bucket.get(i).size(); j++){ ret[index] = bucket.get(i).get(j); index++; } } return ret; } //算出距离的方法 public int dist(int r1, int c1, int r2, int c2){ return Math.abs(r1-r2)+Math.abs(c1-c2); }}
二、答题总结
今天的题目给我的感觉就是好难,救命,有一些思路直接想不到,还有用到的dp、dfs、bfs啥的真的不会,之前没有好好学,只会一个暴力的菜鸡在线卑微,还有机会,现在开始也不晚,奥里给!