题目
Given a 2D integer matrix M representing the gray scale of an image, you need to design a smoother to make the gray scale of each cell becomes the average gray scale (rounding down) of all the 8 surrounding cells and itself. If a cell has less than 8 surrounding cells, then use as many as you can.
Example 1:
Input: [[1,1,1], [1,0,1], [1,1,1]] Output: [[0, 0, 0], [0, 0, 0], [0, 0, 0]] Explanation: For the point (0,0), (0,2), (2,0), (2,2): floor(3/4) = floor(0.75) = 0 For the point (0,1), (1,0), (1,2), (2,1): floor(5/6) = floor(0.83333333) = 0 For the point (1,1): floor(8/9) = floor(0.88888889) = 0
Note:
- The value in the given matrix is in the range of [0, 255].
- The length and width of the given matrix are in the range of [1, 150].
分析及解答
解法:(简洁
)
大神:
stefanpochmann
I store the sums and counts in the higher bits and divide them in a second pass.
public int[][] imageSmoother(int[][] M) {
int m = M.length, n = M[0].length;
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
for (int I=i-1; I<i+2; I++)
for (int J=j-1; J<j+2; J++)
if (I >= 0 && I < m && J >= 0 && J < n)
M[i][j] += 256 + M[I][J] % 256 * 4096;
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
M[i][j] = M[i][j] / 4096 / (M[i][j] / 256 % 16);
return M;
}
After my first pass, each M[i][j] holds:
- In bits 0-7: The original value.
- In bits 8-11: The number of contributing cells (i.e., the number of neighbors, plus 1 (for the cell itself)). That's why I add 256 for each contributing cell.
- In bits 12-31: The sum of the original values of the contributing cells. That's why I add the original value of M[I][J] times 4096.
解法:(下面反例的改进)
class Solution {
public int[][] imageSmoother(int[][] M) {
if(M==null || M.length<1){
return null;
}
int[][] array = new int[M.length][M[0].length];
int[][] dirs = new int[][]{{-1,0},{1,0},{0,1},{0,-1},{-1,-1},{-1,1},{1,1},{1,-1}};//巧妙的数组设置。
for(int i=0;i<M.length;i++){
for(int j=0;j<M[0].length;j++){
int sum=M[i][j];
int count =1;
for(int [] dir:dirs){ //使用数组。
int x=i+dir[0];
int y=j+dir[1];
if(x<0 || x>=M.length || y<0 || y>=M[0].length){ //判断四周的数组是否有效。
continue;
}else{
count++;
sum+=M[x][y];
}
}
array[i][j] = sum/count;
}
}
return array;
}
}
解法:(反例:垃圾的算法)
分为好几次遍历:
* 每个元素影响其下面的元素。
*每个元素影响其上面的元素。
*每个元素影响其斜对角的元素。
class Solution {
public int[][] imageSmoother(int[][] M) {
if(M.length == 1 && M[0].length == 1){
return M;
}
//1.让每个results中的单元,保留周围元素的和。
int results[][] = new int[M.length][M[0].length];
for(int i = 0; i < M.length ; i++){
for(int j = 0; j < M[0].length ;j++){
results[i][j] = M[i][j];
}
}
// 从左向右
for(int i = 0; i < M.length ; i++){
for(int j = 0; j < M[0].length ;j++){
if(i < M.length -1){
results[i+1][j] += M[i][j];
}
if(j < M[0].length-1){
results[i][j+1] += M[i][j];
}
if(i < M.length -1 && j < M[0].length-1){
results[i+1][j+1] += M[i][j];
}
}
}
//从右向左,每个节点去影响周围的元素。
for(int i = M.length -1; i >= 0;i--){
for(int j = M[0].length - 1; j >= 0;j--){
if(i > 0){
results[i-1][j] += M[i][j];
}
if(j > 0){
results[i][j-1] += M[i][j];
if(i > 0 && j > 0){
results[i-1][j-1] += M[i][j];
}
}
}
}
//影响斜对角。
for(int i = 0; i < M.length ; i++){
for(int j = 0; j < M[0].length ;j++){
if(i+1 <= M.length -1 && j-1 >= 0){
results[i+1][j-1] += M[i][j];
}
if(i-1 >=0 && j+1 <= M[0].length -1){
results[i-1][j+1] += M[i][j];
}
}}
//2.计算平均值。
for(int i = 0; i < M.length ; i++){
for(int j = 0; j < M[0].length ;j++){
int count = 9;//记录周围元素的数量
int row = 0;
if(i == 0){
count -= 3;//顶行,去除3个元素
row++;
}
if(i == M.length-1){
count -= 3;//最底行,去除3个元素
row++;
}
if(j == 0){
count -=3;//最左列,去除3个元素
count += row;//加上多去的。(行与列产生了交叉)
}
if(j == M[0].length-1){
count -= 3;
count += row;
}
results[i][j] = results[i][j]/count;
}
}
return results;
}
}