[Easy] 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 red 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., we only count the present cells).
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.
Thinking Process
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 red 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., we only count the present cells).
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.
- Treat the grid as a graph with 4- or 8-directional neighbors.
- Row-major vs column-major traversal affects cache and logic.
- Boundary checks on every neighbor expansion.
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Row/column traversal (this problem) | O(nm) | O(1) | Simulation, spiral |
| BFS/DFS on grid | O(nm) | O(nm) | Islands, shortest path |
| Matrix as graph | O(nm) | O(nm) | 4/8-directional neighbors |
| Transpose / rotate | O(nm) | O(1) | In-place rotation tricks |
Examples
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.833) = 0
For the point (1,1): floor(8/9) = floor(0.888) = 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+100+200+50+200+100)/6) = floor(141.666) = 141
For the point (1,1): floor((50+200+100+200+50+200+100+200+100)/9) = floor(138.888) = 138
Constraints
m == img.lengthn == img[i].length1 <= m, n <= 2000 <= img[i][j] <= 255
Algorithm Breakdown
Key Insight: Boundary Handling
The algorithm handles boundaries correctly by checking bounds before accessing:
class Solution:
def imageSmoother(self, img):
m, n = len(img), len(img[0])
res = [[0] * n for _ in range(m)]
for i in range(m):
for j in range(n):
total = 0
count = 0
for x in range(i - 1, i + 2):
for y in range(j - 1, j + 2):
if 0 <= x < m and 0 <= y < n:
total += img[x][y]
count += 1
res[i][j] = total // count
return res
This ensures:
- Corner cells: Only count 4 neighbors (including itself)
- Edge cells: Only count 6 neighbors (including itself)
- Center cells: Count all 9 neighbors (including itself)
Neighborhood Pattern
For each cell (i, j), the 3×3 neighborhood includes:
(i-1, j-1) (i-1, j) (i-1, j+1)
(i, j-1) (i, j) (i, j+1)
(i+1, j-1) (i+1, j) (i+1, j+1)
Average Calculation
Integer division automatically rounds down:
3 / 4 = 0(not 0.75)5 / 6 = 0(not 0.833)8 / 9 = 0(not 0.888)
Complexity
Time Complexity: O(m × n)
- Outer loops: O(m × n) - iterate through each cell
- Inner loops: O(9) = O(1) - check 9 neighbors (constant)
- Total: O(m × n) where m = rows, n = columns
Space Complexity: O(m × n)
- Result matrix: O(m × n) - store smoothed image
- Variables: O(1) - constant space for counters
- Total: O(m × n)
Key Points
- 3×3 Filter: Standard image smoothing filter
- Boundary Handling: Only count existing neighbors
- Integer Division: Automatically rounds down
- New Matrix: Don’t modify original (use new matrix)
- Simple Logic: Straightforward nested loop approach
Detailed Example Walkthrough
Example: img = [[100,200,100],[200,50,200],[100,200,100]]
Step 1: Process cell (0,0) - corner
Neighbors: (0,0), (0,1), (1,0), (1,1)
Values: 100, 200, 200, 50
Sum = 550, Count = 4
Result: 550/4 = 137
Step 2: Process cell (0,1) - top edge
Neighbors: (0,0), (0,1), (0,2), (1,0), (1,1), (1,2)
Values: 100, 200, 100, 200, 50, 200
Sum = 850, Count = 6
Result: 850/6 = 141
Step 3: Process cell (1,1) - center
Neighbors: All 9 positions
Values: 100,200,100, 200,50,200, 100,200,100
Sum = 1250, Count = 9
Result: 1250/9 = 138
Final result: [[137,141,137],[141,138,141],[137,141,137]]
Edge Cases
- Single cell:
[[5]]→[[5]](only itself) - Single row:
[[1,2,3]]→ average of 3 neighbors per cell - Single column:
[[1],[2],[3]]→ average of 3 neighbors per cell - All same values:
[[5,5,5],[5,5,5],[5,5,5]]→ unchanged - Large values: Works with values up to 255
Common Mistakes
- Skipping edge cases (empty input, single element, boundaries).
- Off-by-one errors in loops and index ranges.
- Forgetting to handle the case when no valid answer exists.
Related Problems
- 661. Image Smoother - Current problem
- 289. Game of Life - Similar neighbor checking
- 733. Flood Fill - Matrix traversal
- 200. Number of Islands - Neighbor exploration
Tags
Matrix, Array, Simulation, Easy
Key Takeaways
- Treat the grid as a graph with 4- or 8-directional neighbors.
- Row-major vs column-major traversal affects cache and logic.
- Boundary checks on every neighbor expansion.
References
- LC 661: Image Smoother on LeetCode
- LeetCode Discuss — LC 661: Image Smoother
- LeetCode Editorial (may require premium)