Rotting Oranges
Problem
We are given a grid where:
0means an empty cell1means a fresh orange2means a rotten orange
Every minute, any fresh orange that is directly adjacent to a rotten orange in the four main directions becomes rotten.
We need to return:
- the minimum number of minutes required so that no fresh orange remains
-1if some fresh orange can never become rotten
Key Insight
This is a classic multi-source BFS problem.
Why multi-source?
Because all initially rotten oranges start spreading rot at the same time.
So instead of running BFS from one rotten orange, we push all rotten oranges into the queue first with time 0.
Then BFS naturally spreads the infection level by level, which matches the "minute by minute" behavior in the problem.
Approach
1. Build the initial queue
We scan the whole grid once.
- if a cell contains a rotten orange, push it into the queue with duration
0 - if a cell contains a fresh orange, mark it as fresh in
visited - if a cell is empty, mark it as unusable
This gives us the correct starting points for BFS.
2. Spread rot using BFS
For each orange popped from the queue:
- update the answer using its current time
- try all four directions
- if a neighboring cell contains a fresh orange, mark it rotten and push it with time
currentTime + 1
Because BFS explores layer by layer, the first time we rot an orange is the minimum time needed to reach it.
3. Check for leftovers
After BFS finishes, if any fresh orange is still left in visited, that means it was unreachable.
So we return -1.
Otherwise, we return the maximum time seen during BFS.
Why This Works
The important observation is that all rotten oranges act simultaneously.
That is exactly what multi-source BFS models:
- all initial rotten oranges are at level
0 - oranges infected after
1minute are at level1 - oranges infected after
2minutes are at level2
and so on.
So the farthest orange reached by BFS determines the total number of minutes needed.
Java Solution
This is your submission:
class Info {
int x;
int y;
int duration;
Info(int x, int y, int duration) {
this.x = x;
this.y = y;
this.duration = duration;
}
}
class Solution {
public int orangesRotting(int[][] grid) {
int n = grid.length;
int m = grid[0].length;
int[][] visited = new int[n][m];
int ans = 0;
Queue<Info> q = new LinkedList<>();
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if (grid[i][j] == 2) {
q.offer(new Info(i, j, 0));
visited[i][j] = 2;
} else if (grid[i][j] == 1){
visited[i][j] = 1;
} else {
visited[i][j] = -1;
}
}
}
int[] rowDir = {0, 1, 0, -1};
int[] colDir = {1, 0, -1, 0};
while(!q.isEmpty()) {
Info node = q.poll();
int x = node.x;
int y = node.y;
int time = node.duration;
ans = Math.max(ans,time);
for(int i = 0; i < 4; i++) {
int newX = x + rowDir[i];
int newY = y + colDir[i];
if(newX >=0 && newX < n && newY >= 0 && newY < m && visited[newX][newY]!=2 && grid[newX][newY] == 1) {
q.offer(new Info(newX, newY, time+1));
visited[newX][newY] = 2;
}
}
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(visited[i][j] == 1) return -1;
}
}
return ans;
}
}
Walkthrough
Take:
grid = [
[2, 1, 1],
[1, 1, 0],
[0, 1, 1]
]
Initially, the orange at (0, 0) is rotten, so it enters the queue with time 0.
Minute 1
It rots:
(0, 1)(1, 0)
Minute 2
Those newly rotten oranges then rot:
(0, 2)(1, 1)
Minute 3
Then:
(2, 1)
Minute 4
Finally:
(2, 2)
So the answer is 4.
Complexity Analysis
Time Complexity: O(n * m)
- we scan the grid once to initialize the queue
- in BFS, each cell is processed at most once
- we scan once more to check if any fresh orange remains
Space Complexity: O(n * m)
- the
visitedmatrix takesO(n * m) - the queue can also take up to
O(n * m)in the worst case
Common Mistakes
1. Starting BFS from only one rotten orange
That is incorrect because all rotten oranges spread at the same time.
2. Not marking an orange as rotten when pushing it
If we wait until pop time, the same fresh orange can be inserted into the queue multiple times.
Your solution handles this correctly by marking visited[newX][newY] = 2 immediately.
3. Forgetting the unreachable case
If BFS ends and some fresh orange is still left, we must return -1.
Small Note On Your Implementation
One thing I like in this solution is that the duration is stored directly inside the queue node.
That keeps the BFS very easy to read:
- pop current orange
- look at its time
- push neighbors with
time + 1
It is simple and maps nicely to the problem statement.
Related Problems
- 01 Matrix — Medium
- Walls and Gates — Medium
- As Far from Land as Possible — Medium