Rotting Oranges
Problem
A grid has cells 0 (empty), 1 (fresh orange) and 2 (rotten orange). Every minute each fresh orange that is next to a rotten orange (up, down, left or right) becomes rotten. Print the number of minutes until no fresh orange is left, or -1 if some fresh orange can never rot. If there is no fresh orange at the start, print 0.
Constraints
- 1 <= r, c <= 500
Examples
Input
3 3 2 1 1 1 1 0 0 1 1
Output
4
Solutions
Starting the BFS from all rotten oranges together makes the time equal to the BFS level. A normal BFS from each orange separately would be much slower and give wrong times.
/*
* Problem : Rotting oranges.
* Input : r and c, then the grid.
* Output : The minutes or -1.
* Approach: Multi-source BFS.
* Time : O(r * c)
* Space : O(r * c)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// This method solves the task. It receives the input and returns the answer.
static int solve(int[][] m) {
int rows = m.length;
int cols = m[0].length;
// Step 1: Put all rotten oranges in the queue at the start (multi-source BFS). Count the fresh oranges.
java.util.ArrayDeque<int[]> queue = new java.util.ArrayDeque<>();
int fresh = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (m[i][j] == 2) {
queue.add(new int[] {i, j, 0});
} else if (m[i][j] == 1) {
fresh++;
}
}
}
// Step 2: BFS in rounds. Each queue item remembers the minute when it rotted.
int[][] moves = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int minutes = 0;
while (!queue.isEmpty()) {
int[] current = queue.poll();
minutes = Math.max(minutes, current[2]);
for (int[] move : moves) {
int x = current[0] + move[0];
int y = current[1] + move[1];
// Step 3: A fresh neighbour rots one minute later. We mark it as rotten at once, so it is added only once.
if (x >= 0 && x < rows && y >= 0 && y < cols && m[x][y] == 1) {
m[x][y] = 2;
fresh--;
queue.add(new int[] {x, y, current[2] + 1});
}
}
}
// Step 4: If a fresh orange is still left, it was never reached.
return fresh == 0 ? minutes : -1;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int rows = scanner.nextInt();
int cols = scanner.nextInt();
int[][] m = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m[i][j] = scanner.nextInt();
}
}
System.out.println(solve(m));
}
}
Hints (1)
- Why start from all rotten oranges at once?