原题链接:Leetcode 661. Image Smoother
An image smoother is a filter of the size 3 x 3 that can be applied to each cell of an image by rounding down the average of the cell and the eight surrounding cells (i.e., the average of the nine cells in the blue smoother). If one or more of the surrounding cells of a cell is not present, we do not consider it in the average (i.e., the average of the four cells in the red smoother).
Given an m x n integer matrix img representing the grayscale of an image, return the image after applying the smoother on each cell of it.
Example 1:
Input: img = [[1,1,1],[1,0,1],[1,1,1]]
Output: [[0,0,0],[0,0,0],[0,0,0]]
Explanation:
For the points (0,0), (0,2), (2,0), (2,2): floor(3/4) = floor(0.75) = 0
For the points (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
Example 2:
Input: img = [[100,200,100],[200,50,200],[100,200,100]]
Output: [[137,141,137],[141,138,141],[137,141,137]]
Explanation:
For the points (0,0), (0,2), (2,0), (2,2): floor((100+200+200+50)/4) = floor(137.5) = 137
For the points (0,1), (1,0), (1,2), (2,1): floor((200+200+50+200+100+100)/6) = floor(141.666667) = 141
For the point (1,1): floor((50+200+200+200+200+100+100+100+100)/9) = floor(138.888889) = 138
Constraints:
- m == img.length
- n == img[i].length
- 1 <= m, n <= 200
- 0 <= img[i][j] <= 255
题目大意:
有一个 m x n
的矩阵 img
,定义 img[i][j]
的平均值是以 img[i][j]
为中心的九宫格的值的平均值。
当 img[i][j]
周围的格子不能构成九宫格时,有多少就按多少来算平均值。
最后以二维数组的形式返回矩阵 img
的平均值
方法一:模拟
思路:
m、n的最大值是200,也就是说矩阵的最高规模是200 x 200
可以直接模拟,挨个求平均值
C++ 代码:
class Solution {
public:
vector<vector<int>> imageSmoother(vector<vector<int>>& img) {
// m行 n列
int m = img.size(), n = img[0].size();
// 初始化结果数组ans
vector<vector<int>> ans(m, vector<int>(n));
for(int i = 0; i < m; i++ ){
for(int j = 0; j < n; j++ ){
// sum总和 num是组成对应item的个数
int sum = 0, num = 0;
// xy为偏移量
for(int x = - 1; x <= 1; x++ ){
for(int y = -1; y <= 1; y++ ){
if(i + x >= 0 && i + x < m && j + y >= 0 && j + y < n){
num++;
sum += img[i + x][j + y];
}
}
}
ans[i][j] = sum / num;
}
}
return ans;
}
};
复杂度分析;
- 时间复杂度:O(mn),两重循环遍历每个cell,对于每个cell的计算是不超过9个值求平均值。
- 空间复杂度:O(1)
方法二:二维前缀和
c++代码:
class Solution {
public:
vector<vector<int>> imageSmoother(vector<vector<int>>& img) {
// m行号 n列号
int m = img.size();
int n = img[0].size();
// 定义前缀和数组
vector<vector<int>> pre(m+1, vector<int>(n+1, 0));
// 预处理 下标从1开始
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
pre[i][j] = pre[i-1][j] + pre[i][j-1] - pre[i-1][j-1] + img[i-1][j-1];
}
}
// 结果数组
vector<vector<int>> ans(m, vector<int>(n, 0));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 确定范围
int left = max(j-1, 0);
int right = min(j+1, n-1);
int top = max(i-1, 0);
int bottom = min(i+1, m-1);
int cnt = (bottom - top + 1) * (right - left + 1);
int sum = pre[bottom+1][right+1] - pre[top][right+1] - pre[bottom+1][left] + pre[top][left];
ans[i][j] = sum / cnt;
}
}
return ans;
}
};