About Us Services Blog Contact Us Learn

Rotting Oranges - DSA Graphs


Rotting Oranges - DSA Graphs

problem link: Rotting Oranges

Problem Statement

You are given an 𝑛 × 𝑚 grid where each cell can have one of three values:

  • 0 → An empty cell
  • 1 → A fresh orange
  • 2 → A rotten orange

A rotten orange can rot adjacent fresh oranges (4-directionally: up, down, left, right) in one minute. Your task is to determine the minimum time required to rot all fresh oranges. If it's impossible to rot all oranges, return -1.

What Does 4-Directional Neighbor Mean?

Each orange in the grid has four possible neighbors:

  • Up: (row - 1, same column)
  • Down: (row + 1, same column)
  • Left: (same row, column - 1)
  • Right: (same row, column + 1)

If a fresh orange is present in any of these positions next to a rotten orange, it will rot in the next minute.

Understanding the Problem with Examples

Example 1

Input:

    [[2,1,1],
     [1,1,0],
     [0,1,1]]
    

Step-by-step rotting process:

  1. Initially, the rotten orange at (0,0) can rot its adjacent fresh oranges.
                [[2,2,1],
                 [2,1,0],
                 [0,1,1]]
                
    Time = 1 minute
  2. Next minute, the newly rotten oranges at (0,1) and (1,0) spread rotting further:
                [[2,2,2],
                 [2,2,0],
                 [0,1,1]]
                
    Time = 2 minutes
  3. Third minute, the remaining fresh oranges rot:
                [[2,2,2],
                 [2,2,0],
                 [0,2,1]]
                
    Time = 3 minutes
  4. Final state:
                [[2,2,2],
                 [2,2,0],
                 [0,2,2]]
                
    Time = 4 minutes

Output:

4

Example 2

Input:

    [[2,1,1],
     [0,1,1],
     [1,0,1]]
    

Step-by-step rotting process:

  1. Initially, the rotten orange at (0,0) starts spreading
                [[2,2,1],
                 [0,1,1],
                 [1,0,1]]
                
    Time = 1 minute
  2. Next minute, the newly rotten orange at (0,1) spreads to (0,2):
                [[2,2,2],
                 [0,2,1],
                 [1,0,1]]
                
    Time = 2 minutes
  3. Next minute:
                [[2,2,2],
                 [0,2,2],
                 [1,0,1]]
                
    Time = 3 minutes
  4. Next minute:
                [[2,2,2],
                 [0,2,2],
                 [1,0,2]]
                
    Time = 4 minutes
  5. At this point, the rotting process stops!
    • The fresh oranges at (2,0) is completely isolated because there is no path from any rotten orange to it.
    • Since this fresh orange cannot be reached, it will never rot.

Final State:

    [[2,2,2],
     [0,2,2],
     [1,0,2]]
    

Since some fresh oranges remain unrotted, we return -1.

Output:

-1

Key Observations

Queue Initialization

We start by identifying all the rotten oranges and storing their positions in a queue.

This helps us process all rotten oranges at the same time (layer by layer), ensuring that the rotting spreads efficiently.

Layer-by-Layer Processing in BFS

When we say "layer-by-layer", we mean that at each minute, we process all the rotten oranges present in the queue simultaneously before moving to the next batch of newly rotten oranges.

In a single BFS step (one minute),:

  • We remove all currently rotten oranges from the queue.
  • For each rotten orange, we check its 4-directional neighbors (up, down, left, right).
  • If a fresh orange is found in any of these positions, it rots and is added to the queue for processing in the next minute.

This ensures that the rotting process happens in waves, affecting all fresh oranges adjacent to rotten ones at the same time.

Count Fresh Oranges

Count the total number of fresh oranges in the grid. This helps determine when all fresh oranges have rotted and when to stop the process.

Perform BFS Traversal

We process each rotten orange from the queue, checking its 4-directional neighbors.

If a neighboring cell contains a fresh orange, it will rot and be added to the queue for the next round.

Track Time in Minutes

Each BFS iteration represents one minute. We keep track of how many minutes it takes for all reachable fresh oranges to rot.

Edge Case - Isolated Fresh Oranges

If, after BFS, there are still fresh oranges left (i.e., they could not be reached by any rotten orange), return -1.


Code Implementations

Below are the implementations in Java and C++.

JAVA


 import java.util.LinkedList;
    import java.util.Queue;

    class Solution {
        public int orangesRotting(int[][] grid) {
            int rows = grid.length;
            int cols = grid[0].length;
            Queue queue = new LinkedList<>();
            int freshOranges = 0;

            // Step 1: Add all initially rotten oranges to the queue
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    if (grid[i][j] == 2) {
                        queue.add(new int[]{i, j});
                    } else if (grid[i][j] == 1) {
                        freshOranges++;
                    }
                }
            }

            if (freshOranges == 0) return 0; // No fresh oranges to rot

            int minutes = 0;
            int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 4-directional movement

            // Step 2: Perform BFS layer by layer
            while (!queue.isEmpty()) {
                int size = queue.size();
                boolean rottedThisMinute = false;

                for (int i = 0; i < size; i++) {
                    int[] rotten = queue.poll();
                    int r = rotten[0], c = rotten[1];

                    for (int[] dir : directions) {
                        int nr = r + dir[0], nc = c + dir[1];
                        if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] == 1) {
                            grid[nr][nc] = 2; // Rot the fresh orange
                            queue.add(new int[]{nr, nc});
                            freshOranges--;
                            rottedThisMinute = true;
                        }
                    }
                }

                // If there were no rotting this minute, it means some fresh oranges are unreachable
                if (rottedThisMinute) {
                    minutes++;
                }
            }

            return freshOranges == 0 ? minutes : -1;
        }
    }
        

Time and Space Complexity Analysis

Time Complexity: O(N × M)

  • Each cell in the grid is processed at most once during the BFS traversal.
  • We traverse through all the cells in the grid initially to count fresh oranges and add rotten ones to the queue (O(N × M)).
  • The BFS traversal also visits each cell at most once, making the total complexity O(N × M).

Space Complexity: O(N × M)

  • The worst-case scenario occurs when all oranges are fresh except one rotten orange.
  • In such a case, the queue stores almost all the oranges at some point.
  • Since we use an auxiliary queue for BFS, the space complexity remains O(N × M).

Conclusion

  • We used BFS (Breadth-First Search) to spread the rotting process layer by layer efficiently.
  • The problem was solved optimally in O(N × M) time, making it efficient for large grids.
  • If any fresh orange remains unrotted, we return -1. Otherwise, we return the minimum time required for all oranges to rot.
  • The key takeaway is that BFS is ideal for shortest-path problems in an unweighted grid, ensuring all elements in a layer are processed simultaneously.

Recent Posts