994. Rotting Oranges
Description of Problem
You are given an m x n grid where each cell can have one of three values:
0representing an empty cell,1representing a fresh orange, or2representing 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.
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.lengthn == grid[i].length1 <= m, n <= 10grid[i][j]is0,1, or2.
Solution
Tags: Breadth First Search
Explanation
Very simple, just use BFS to simulate the process of rotting oranges.
Code (Rust)
#[derive(Clone, Copy, Debug, PartialEq)]
enum Colour{
White,
Gray,
Black,
}
use Colour::{White, Gray, Black};
impl Solution {
pub fn oranges_rotting(grid: Vec<Vec<i32>>) -> i32 {
use std::collections::VecDeque;
let m = grid.len();
let n = grid[0].len();
let mut colours = vec![ vec![White ;n];m ];
let mut depth = 0;
let mut queue1 = VecDeque::new();
let mut queue2 = VecDeque::new();
let mut count_rotten = 0;
let mut count_fresh = 0;
// Put all rotten organges into queue1
for i in 0..m{
for j in 0..n{
if grid[i][j] == 2 {
queue1.push_back((i,j));
colours[i][j] = Black;
count_rotten+=1;
}else if grid[i][j] == 1 {
count_fresh+=1;
}
}
}
// Deal with special cases
// Case 1: The grid has no fresh oranges
if count_fresh == 0 {
return 0;
}
// Case 2: The grid has only fresh oranges
else if count_rotten == 0{
return -1;
}
// Case 3: The grid has fresh oranges and rotton oranges
while !queue1.is_empty(){
while let Some((i,j)) = queue1.pop_front(){
// UP
if Self::is_available(&grid, &colours, i-1, j, m, n) {
colours[i-1][j] = Gray;
queue2.push_back((i-1, j));
}
// LEFT
if Self::is_available(&grid, &colours, i, j-1, m, n) {
colours[i][j-1] = Gray;
queue2.push_back((i,j-1));
}
// RIGHT
if Self::is_available(&grid, &colours, i, j+1, m, n) {
colours[i][j+1] = Gray;
queue2.push_back((i,j+1));
}
// BOTTOM
if Self::is_available(&grid, &colours, i+1, j, m, n) {
colours[i+1][j] = Gray;
queue2.push_back((i+1,j));
}
// Finish the exploration of the node
colours[i][j] = Black;
}
depth+=1;
let temp = queue1;
queue1 = queue2;
queue2 = temp;
}
// Check whether all oranges are rotten?
for i in 0..m{
for j in 0..n{
if colours[i][j] != Black && (grid[i][j] == 2 || grid[i][j] == 1) {
return - 1;
}
}
}
return depth - 1;
}
#[inline(always)]
fn is_available(
grid: &Vec<Vec<i32>>,
colours : &Vec<Vec<Colour>>,
i : usize,
j : usize,
m : usize,
n : usize
) -> bool {
return
0 <= i && i < m
&& 0 <= j && j < n
&& grid[i][j] == 1
&& colours[i][j] == White
;
}
}
Complexity
Time Complexity
- \( T(m,n) = O(m \cdot n) \)