3.8 KiB
Leetcode Rotting-Oranges
2022-07-17 15:12
Algorithms:
#algorithm #BFS
Data structures:
#DS #vector_2d
Difficulty:
#coding_problem #difficulty-medium
Additional tags:
#leetcode
Revisions:
N/A
Related topics:
Links:
Problem
You are given an m x n
grid
where each cell can have one of three values:
0
representing an empty cell,1
representing a fresh orange, or2
representing a rotten orange.
Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.
Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1
.
Examples
Example 1:
**Input:** grid = [[2,1,1],[1,1,0],[0,1,1]]
**Output:** 4
Example 2:
**Input:** grid = [[2,1,1],[0,1,1],[1,0,1]]
**Output:** -1
Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.
Example 3:
**Input:** grid = [[0,2]]
**Output:** 0
Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.
Constraints
m == grid.length
n == grid[i].length
1 <= m, n <= 10
grid[i][j]
is0
,1
, or2
.
Thoughts
[!summary] This is a #BFS problem, because we use it to calculate the shortest {time, distance}
Be wary of these special cases:
- everything is empty cell -> return -1, no orange => no fresh orange
- everything is rotten -> return 0
- everything is fresh -> return -1, impossible to rot
[!tip] update the value in place vs. in queue Update in place, such as
if (grid[a + 1][b] != 0) { queue.push({a, b}); grid[a + 1][b] = 0; }
Can avoid multiple enqueues, because the value is already updated, so another node in queue can't push that again.
grid[a][b] = 0; if (grid[a + 1][b] != 0) { queue.push({a, b}); }
this code might result in pushing the same node twice.
Solution
class Solution {
public:
int orangesRotting(vector<vector<int>> &grid) {
// BFS
queue<pair<int, int>> todo;
int m = grid.size(), n = grid[0].size();
int time = -1;
bool isGridEmpty = true;
int freshCount = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 2) {
// add to queue, rotten
todo.push({i, j});
} else if (grid[i][j] == 1) {
freshCount++;
}
if (isGridEmpty && grid[i][j] != 0) {
isGridEmpty = false;
}
}
}
int x, y;
int offset[] = {-1, 1};
int newX, newY;
// if there is no value, there's no orange -> no fresh orange
if (isGridEmpty) {
return 0;
}
while (!todo.empty()) {
for (int i = 0, size = todo.size(); i < size; i++) {
x = todo.front().first;
y = todo.front().second;
todo.pop();
for (int o : offset) {
newX = x + o;
if (newX >= 0 && newX < m && grid[newX][y] == 1) {
todo.push({newX, y});
// cout<<"Pushed: "<<newX<<", "<<y<<'\n';
grid[newX][y] = 2;
freshCount--;
}
newY = y + o;
if (newY >= 0 && newY < n && grid[x][newY] == 1) {
todo.push({x, newY});
// cout<<"Pushed: "<<x<<", "<<newY<<'\n';
grid[x][newY] = 2;
freshCount--;
}
}
}
time++;
}
// check again if there is a fresh orange
if (freshCount != 0) {
return -1;
}
return time;
}
};