包含整数的二维矩阵 M 表示一个图片的灰度。你需要设计一个平滑器来让每一个单元的灰度成为平均灰度 (向下舍入) ,平均灰度的计算是周围的8个单元和它本身的值求平均,如果周围的单元格不足八个,则尽可能多的利用它们。
输入:
[[1,1,1],
[1,0,1],
[1,1,1]]
输出:
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
看到这个题目一开始没啥思路,只有暴力的想法。后来看到别人的思路发现非常神奇,涨姿势了。
首先可以用到的就是方向向量法。把需要操作的格子做成一个方向向量表,遍历向量表操作,同时加上筛选条件,选取需要的格子。代码如下:
class Solution {
public int[][] imageSmoother(int[][] M) {//方向向量法
int r = M.length;
int c = M[0].length;
int[][] dir = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,0},{0,1},{1,-1},{1,0},{1,1}};
int[][] res = new int[r][c];
for(int i = 0; i< r; i++)
for(int j = 0; j< c; j++)
{
int sum = 0;
int count = 0;
for(int[] d : dir)
{
int x = i +d[0];
int y = j +d[1];
if(x < 0 || x >= r || y < 0 || y >= c) continue;
sum += M[x][y];
count++;
}
res[i][j] = sum/count;
}
return res;
}
}
看到大家的讨论,还有一种比较简单的方式,那就是小区域法。
最终我需要求和的只是一片矩阵小区域,所以可以把小区域的边界找出来。然后再遍历小区域里面的所有格子。代码如下。
class Solution {
public int[][] imageSmoother(int[][] M) {//小区域法
int r = M.length;
int c = M[0].length;
int[][] res = new int[r][c];
for(int i = 0; i< r; i++)
for(int j = 0; j< c; j++)
{
int pu = i-1 < 0 ? i : i-1;
int pd = i+1 >=r ? i : i+1;
int pl = j-1 < 0 ? j : j-1;
int pr = j+1 >=c ? j : j+1;
int sum = 0;
for(int x = pu ; x<= pd; x++)
for(int y = pl; y<= pr; y++ )
sum += M[x][y];
res[i][j] = sum/((pd-pu+1)*(pr-pl+1));
}
return res;
}
}
不过,总的来说,方向向量会更灵活一点,哪些格子可以任意选取,不一定要矩形。