githubEdit

22. Rotten Oranges

βœ… GFG solution to the Rotten Oranges problem: find minimum time for all oranges to rot using multi-source BFS level-by-level traversal. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

You are given a matrix mat[][] where each cell has one of three values:

  • 0 β€” Empty cell

  • 1 β€” Cell with a fresh orange

  • 2 β€” Cell with a rotten orange

A rotten orange at index (i, j) can rot adjacent fresh oranges at (i-1, j), (i+1, j), (i, j-1), (i, j+1) in one unit of time.

Your task is to determine the minimum time required so that all the oranges become rotten. If it is impossible to rot every orange, return -1.

πŸ“˜ Examples

Example 1

Input: mat[][] = [[2, 1, 0, 2, 1],
                  [1, 0, 1, 2, 1],
                  [1, 0, 0, 2, 1]]
Output: 2
Explanation: Oranges at (0,0), (0,3), (1,3), and (2,3) rot adjacent fresh oranges in successive 
time frames. All fresh oranges become rotten after 2 units of time.

Example 2

πŸ”’ Constraints

  • $1 \le \text{mat.size()} \le 500$

  • $1 \le \text{mat[0].size()} \le 500$

  • $\text{mat}[i][j] \in {0, 1, 2}$

βœ… My Approach

The optimal approach uses Multi-Source BFS (Breadth-First Search) β€” treating all initially rotten oranges as simultaneous BFS starting points and spreading rot level by level:

Multi-Source BFS (Level-Order Traversal)

  1. Initialize:

    • Scan the entire matrix. Push all rotten orange positions (i, j) into the queue and count all fresh oranges.

    • If fresh == 0 initially, return 0 immediately.

  2. BFS Level by Level:

    • Each BFS level represents one unit of time.

    • For every rotten orange in the current level, try to rot all 4 adjacent fresh neighbors.

    • Mark newly rotted oranges as 2, decrement fresh, and push them into the queue for the next level.

  3. Early Exit:

    • The outer while loop has condition !q.empty() && fresh > 0, so BFS stops as soon as all fresh oranges are rotted β€” no unnecessary iterations.

  4. Final Check:

    • If fresh > 0 after BFS completes, isolated fresh oranges exist β€” return -1.

    • Otherwise return time (number of BFS levels processed).

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(n Γ— m), as every cell in the matrix is visited at most once during the BFS traversal, where n and m are the number of rows and columns respectively.

  • Expected Auxiliary Space Complexity: O(n Γ— m), as the BFS queue can hold at most all cells of the matrix in the worst case when all oranges are initially rotten.

πŸ–₯️ Code (C)

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ BFS Without Modifying Input (Distance Array)

πŸ’‘ Algorithm Steps:

  1. Allocate a dist[][] grid initialized to -1 to track earliest rot time for each cell, leaving the original matrix untouched.

  2. Push all initially rotten positions into the queue and set their dist to 0.

  3. Standard BFS: for each dequeued cell, attempt to rot all 4 unvisited fresh neighbors, setting dist[nx][ny] = dist[x][y] + 1.

  4. Track the maximum distance seen. If fresh is still non-zero after BFS, return -1.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n Γ— m) β€” Each cell is enqueued and dequeued at most once

  • Auxiliary Space: πŸ’Ύ O(n Γ— m) β€” Extra distance grid plus the BFS queue

βœ… Why This Approach?

  • Completely non-destructive β€” the original matrix is never modified

  • The distance grid is useful when you need to know when each cell rotted

  • Cleaner separation between input data and BFS state


πŸ“Š 3️⃣ BFS Using Index Encoding (No Pair Overhead)

πŸ’‘ Algorithm Steps:

  1. Encode cell (i, j) as a single integer i*m + j to store in a plain integer queue, avoiding pair or struct allocation.

  2. During BFS, decode with x = encoded / m, y = encoded % m for neighbor computation.

  3. Track fresh count and BFS levels identically to the main approach.

  4. Return -1 if fresh remains, else return the number of levels elapsed.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n Γ— m) β€” Single complete BFS pass

  • Auxiliary Space: πŸ’Ύ O(n Γ— m) β€” Integer queue can hold at most all cells

βœ… Why This Approach?

  • Integer queue is more cache-friendly than a pair queue β€” each element is 4 bytes vs 8 bytes

  • Compact encoding reduces queue memory footprint by half

  • Preferred in competitive programming where constant factors matter


πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time

πŸ’Ύ Space

βœ… Pros

⚠️ Cons

🏷️ Fresh-Count BFS (Main)

🟒 O(nΓ—m)

🟒 O(nΓ—m)

πŸš€ Early exit, clean logic

πŸ”§ Mutates input matrix

πŸ—ΊοΈ Distance Array BFS

🟒 O(nΓ—m)

🟑 O(nΓ—m) extra

πŸ“– Non-destructive, debug-friendly

πŸ’Ύ Extra distance grid needed

πŸ”’ Index-Encoded BFS

🟒 O(nΓ—m)

🟒 O(nΓ—m)

⭐ Cache-friendly, minimal overhead

πŸ”§ Manual encode/decode logic

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended

πŸ”₯ Rating

πŸ… General / Interviews

πŸ₯‡ Fresh-Count BFS

β˜…β˜…β˜…β˜…β˜…

πŸ”’ Read-only input constraint

πŸ₯ˆ Distance Array BFS

β˜…β˜…β˜…β˜…β˜†

⚑ Competitive / Tight memory

πŸ₯‰ Index-Encoded BFS

β˜…β˜…β˜…β˜…β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated