Rotten Oranges

Given a matrix mat[][] of dimension n * m where each cell in the matrix can have values 0, 1 or 2 which has the following meaning:
: Empty cell
1 : Cell have fresh oranges
2 : Cell have rotten oranges

We have to determine what is the earliest time after which all the oranges are rotten. A rotten orange at index (i, j) can rot other fresh orange at indexes (i-1, j), (i+1, j), (i, j-1), (i, j+1) (updownleft and right) in a unit time.

Note: Your task is to return the minimum time to rot all the fresh oranges. If not possible returns -1.

Examples:

Input: mat[][] = [[0, 1, 2], [0, 1, 2], [2, 1, 1]]
Output: 1
Explanation: Oranges at positions (0,2), (1,2), (2,0) will rot oranges at (0,1), (1,1), (2,2) and (2,1) in unit time.
Input: mat[][] = [[2, 2, 0, 1]]
Output: -1
Explanation: Oranges at (0,0) and (0,1) can't rot orange at (0,3).
Input: mat[][] = [[2, 2, 2], [0, 2, 0]]
Output: 0
Explanation: There is no fresh orange. 

Constraints:
1 ≤ mat.size() ≤ 500
1 ≤ mat[0].size() ≤ 500
mat[i][j] = {0, 1, 2} 


Approach 01:

#include <vector>
#include <queue>

using namespace std;

class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int rows = grid.size(), cols = grid[0].size();
        queue<pair<int, int>> rottenQueue;
        int freshCount = 0;

        // Identify initial rotten oranges and count fresh oranges
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == 2) {
                    rottenQueue.push({i, j});
                } else if (grid[i][j] == 1) {
                    freshCount++;
                }
            }
        }

        int minutesElapsed = 0;
        vector<vector<int>> visited(rows, vector<int>(cols, 0));
        vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

        while (!rottenQueue.empty()) {
            int queueSize = rottenQueue.size();
            minutesElapsed++;

            while (queueSize--) {
                pair<int, int> cell = rottenQueue.front();
                int row = cell.first, col = cell.second;
                rottenQueue.pop();

                for (size_t i = 0; i < directions.size(); i++) {
                    int newRow = row + directions[i].first;
                    int newCol = col + directions[i].second;
                    
                    if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols &&
                        visited[newRow][newCol] == 0 && grid[newRow][newCol] == 1) {
                        freshCount--;
                        rottenQueue.push({newRow, newCol});
                        visited[newRow][newCol] = 1;
                    }
                }
            }
        }

        return freshCount == 0 ? max(0, minutesElapsed - 1) : -1;
    }
};
from collections import deque
from typing import List

class Solution:
    def orangesRotting(self, grid: List[List[int]]) -> int:
        rows, cols = len(grid), len(grid[0])
        rottenQueue = deque()
        freshOranges = 0

        for i in range(rows):
            for j in range(cols):
                if grid[i][j] == 2:
                    rottenQueue.append((i, j))
                elif grid[i][j] == 1:
                    freshOranges += 1

        minutesElapsed = 0
        visited = [[0] * cols for _ in range(rows)]
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

        while rottenQueue:
            levelSize = len(rottenQueue)
            minutesElapsed += 1

            for _ in range(levelSize):
                row, col = rottenQueue.popleft()

                for dRow, dCol in directions:
                    newRow, newCol = row + dRow, col + dCol
                    if 0 <= newRow < rows and 0 <= newCol < cols and visited[newRow][newCol] == 0 and grid[newRow][newCol] == 1:
                        freshOranges -= 1
                        rottenQueue.append((newRow, newCol))
                        visited[newRow][newCol] = 1

        return max(0, minutesElapsed - 1) if freshOranges == 0 else -1

 

Time Complexity:

  • Grid Traversal:

    Each cell in the grid is visited once during initialization, contributing \( O(R \times C) \), where \( R \) is the number of rows and \( C \) is the number of columns.

  • BFS Processing:

    Each fresh orange is processed once when it turns rotten, leading to a worst-case complexity of \( O(R \times C) \).

  • Total Time Complexity:

    The overall time complexity is \( O(R \times C) \).

Space Complexity:

  • Queue Storage:

    In the worst case, all oranges could be stored in the queue, requiring \( O(R \times C) \) space.

  • Visited Grid:

    A separate \( R \times C \) grid is used to track visited cells, contributing \( O(R \times C) \) space.

  • Total Space Complexity:

    The overall space complexity is \( O(R \times C) \).

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top