How Long Until Every Fresh Fruit Spoils
Solve this ProblemA crate is laid out as a grid. Each cell is empty (0), holds a fresh fruit (1) or holds a spoiled fruit (2). Every minute, every fresh fruit that touches a spoiled fruit on one of its four sides becomes spoiled. Return the minimum number of minutes after which no fresh fruit is left, or -1 if that never happens.
Think of each cell as a node, connected to its four neighbours: the spoilage spreads exactly like a breadth-first search that begins at all the spoiled fruits simultaneously.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ rows, cols ≤ 12; grid[r][c] is 0 (empty crate slot), 1 (fresh fruit) or 2 (spoiled fruit) - ◆
Every minute, each fresh fruit that is directly above, below, left or right of a spoiled fruit becomes spoiled (spoilage does not pass through empty slots or diagonally) - ◆
Return the minimum number of minutes until no fresh fruit remains. If some fresh fruit can never be reached, return -1. If there is no fresh fruit to begin with, return 0 - ◆
The grid is a graph in which every cell is a node and cells that share a side are connected
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Simulate Minute by Minute, Rescanning the Whole Grid
BruteSimulate the spoilage literally. In each round scan every cell; for every spoiled fruit, note the fresh neighbours that would spoil this minute. If nobody would spoil, stop. Otherwise turn all those neighbours to spoiled at once (deciding first and applying afterwards makes the round a single minute) and count one minute. At the end, any remaining fresh fruit means -1. Every round re-scans the whole grid, including the old spoiled cells that can no longer spread anything new, so a long winding path costs O(R·C) rounds of O(R·C) work.
O((R·C)²)O(R·C)1class Solution {
2 public int minutesToSpoil(int[][] grid) {
3 int rows = grid.length, cols = grid[0].length;
4 int[] dr = {1, -1, 0, 0};
5 int[] dc = {0, 0, 1, -1};
6 int minutes = 0;
7 while (true) {
8 List<int[]> spoiled = new ArrayList<>();
9 for (int r = 0; r < rows; r++) {
10 for (int c = 0; c < cols; c++) {
11 if (grid[r][c] != 2) continue;
12 for (int d = 0; d < 4; d++) {
13 int nr = r + dr[d], nc = c + dc[d];
14 if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] == 1) {
15 spoiled.add(new int[]{nr, nc});
16 }
17 }
18 }
19 }
20 if (spoiled.isEmpty()) break;
21 for (int[] cell : spoiled) grid[cell[0]][cell[1]] = 2;
22 minutes++;
23 }
24 for (int[] row : grid) {
25 for (int v : row) {
26 if (v == 1) return -1;
27 }
28 }
29 return minutes;
30 }
31}Optimal — Multi-Source Breadth-First Search, One Level per Minute
OptimalSpoilage moves outward one step per minute from ALL spoiled fruits at the same time — exactly a breadth-first search that starts from many sources. Put every initially spoiled cell in a queue and count the fresh fruits. Then process the queue level by level: all cells currently in the queue are the ones that became spoiled in the previous minute; each spoils its fresh neighbours (mark them spoiled at once, decrease the fresh count, and queue them for the next minute). One level = one minute. Stop when the queue is empty or no fresh fruit is left; if fresh fruit remains, it was unreachable: -1. Each cell enters the queue at most once: O(R·C).
O(R·C)O(R·C)1class Solution {
2 public int minutesToSpoil(int[][] grid) {
3 int rows = grid.length, cols = grid[0].length;
4 int[] dr = {1, -1, 0, 0};
5 int[] dc = {0, 0, 1, -1};
6 Deque<int[]> queue = new ArrayDeque<>();
7 int fresh = 0;
8 for (int r = 0; r < rows; r++) {
9 for (int c = 0; c < cols; c++) {
10 if (grid[r][c] == 2) queue.add(new int[]{r, c});
11 else if (grid[r][c] == 1) fresh++;
12 }
13 }
14 int minutes = 0;
15 while (!queue.isEmpty() && fresh > 0) {
16 int size = queue.size();
17 for (int i = 0; i < size; i++) {
18 int[] cell = queue.poll();
19 for (int d = 0; d < 4; d++) {
20 int nr = cell[0] + dr[d], nc = cell[1] + dc[d];
21 if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] == 1) {
22 grid[nr][nc] = 2;
23 fresh--;
24 queue.add(new int[]{nr, nc});
25 }
26 }
27 }
28 minutes++;
29 }
30 return fresh == 0 ? minutes : -1;
31 }
32}