AlgoMaster Logo

Rotting Oranges

Last Updated: March 28, 2026

medium
3 min read

Understanding the Problem

We have a grid of oranges. Rotten oranges spread rot to their fresh neighbors every minute, all at the same time. We need to figure out how many minutes it takes for every fresh orange to become rotten, or determine that some fresh oranges can never be reached.

The simultaneous spreading is the key detail here. All rotten oranges infect their neighbors at the same time during each minute. This is not a scenario where one rotten orange finishes spreading before another starts. They all act in parallel. That parallel, level-by-level expansion is what makes this a BFS problem rather than a DFS problem.

The other important detail is the -1 case. If any fresh orange is completely cut off from all rotten oranges by empty cells, it can never rot, and we return -1.

Key Constraints:

  • 1 <= m, n <= 10 -> The grid is at most 10x10 = 100 cells. Even an O(n^2 * m^2) brute force would handle this easily. But BFS is the natural fit for modeling simultaneous spreading.
  • grid[i][j] is 0, 1, or 2 -> Only three possible values. No negative numbers or special values to worry about.

Approach 1: Brute Force Simulation

Intuition

The most direct approach is to literally simulate what the problem describes. Each minute, scan the entire grid and find every fresh orange adjacent to a rotten orange. Mark those fresh oranges as rotten. Repeat until nothing changes. Count the minutes.

The catch is that we need to be careful about the order of updates. If we rot an orange and immediately use it to rot its neighbors in the same scan, we are letting rot spread too far in a single minute. So we need to separate "oranges that were already rotten at the start of this minute" from "oranges that just became rotten this minute."

Algorithm

  1. Count all fresh oranges in the grid.
  2. Initialize minutes = 0.
  3. In each round, scan the entire grid. For each fresh orange adjacent to a rotten orange, mark it for rotting.
  4. After the full scan, apply all the rotting marks. Decrement the fresh count for each newly rotten orange.
  5. If any oranges rotted this round, increment minutes and repeat. If none rotted, stop.
  6. If fresh oranges remain, return -1. Otherwise, return minutes.

Example Walkthrough

1Initial grid: 2=rotten, 1=fresh, 0=empty. fresh=6
0
1
2
0
rotten
2
1
1
1
1
1
0
2
0
1
1
1/5

Code

This approach works but redundantly scans the entire grid every minute. What if we only tracked the newly rotten oranges and processed just those?

Approach 2: Multi-source BFS

Intuition

Here is the key insight: rot spreading from multiple sources simultaneously is exactly what multi-source BFS does. Instead of running BFS from one starting point, we load all initial rotten oranges into the queue before starting. Then BFS processes them level by level. Each level corresponds to one minute of elapsed time.

Think of it like dropping multiple pebbles into a pond at the same time. Each pebble creates its own ripple, and the ripples expand outward simultaneously. The BFS queue naturally handles this. All the initial rotten oranges go in first (level 0), then their fresh neighbors become rotten (level 1), then those neighbors' fresh neighbors (level 2), and so on.

We also track the count of fresh oranges. Every time we rot a fresh orange during BFS, we decrement the count. When BFS finishes, if any fresh oranges remain, those oranges were unreachable and we return -1.

Algorithm

  1. Scan the grid. Add all rotten oranges to a queue. Count all fresh oranges.
  2. If there are no fresh oranges, return 0 immediately.
  3. Run BFS. For each level (minute), process all oranges currently in the queue.
  4. For each rotten orange, check its 4 neighbors. If a neighbor is fresh, mark it rotten, decrement the fresh count, and add it to the queue.
  5. After processing a full level, increment the minute counter (only if we actually rotted something).
  6. When the queue is empty, check: if fresh == 0, return minutes. Otherwise, return -1.

Example Walkthrough

1Initial: seed queue with all rotten oranges. Queue=[(0,0)], fresh=6
0
1
2
0
queue
2
1
1
1
1
1
0
2
0
1
1
1/6

Code