目录
一、练习题目
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<Integer>> shiftGrid(int[][] grid, int k) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
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<Integer> tmp = new ArrayList<Integer>();
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<n && k1>=0 && l<m && 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<int[]>> bucket = new ArrayList<List<int[]>>();
// 赋给桶的大小,最大为距离最大,距离一样的放在一个桶。
for(int i=0; i<=maxDist; i++){
bucket.add(new ArrayList<int[]>());
}
//调用方法计算出距离,然后把坐标放在对应的桶中。
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啥的真的不会,之前没有好好学,只会一个暴力的菜鸡在线卑微,还有机会,现在开始也不晚,奥里给!