logseq_notes/pages/OJ notes/pages/Leetcode Rotting-Oranges.md
2023-06-14 14:27:22 +08:00

3.7 KiB

Leetcode Rotting-Oranges

2022-07-17 15:12

Algorithms:

#algorithm #BFS

Data structures:

#DS #vector_2d

Difficulty:

#coding_problems #difficulty_medium

Additional tags:

#leetcode

Revisions:

N/A

Problem

You are given an m x n grid where each cell can have one of three values:

  • 0 representing an empty cell,

  • 1 representing a fresh orange, or

  • 2 representing a rotten orange.

    Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.

    Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1.

Examples

Example 1:

**Input:** grid = [[2,1,1],[1,1,0],[0,1,1]]
**Output:** 4

Example 2:

**Input:** grid = [[2,1,1],[0,1,1],[1,0,1]]
**Output:** -1

Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.

Example 3:

**Input:** grid = [[0,2]]
**Output:** 0

Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.

Constraints

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 10
  • grid[i][j] is 0, 1, or 2.

Thoughts

[!summary] This is a #BFS problem, because we use it to calculate the shortest {time, distance}

Be wary of these special cases:

  • everything is empty cell -> return -1, no orange => no fresh orange

  • everything is rotten -> return 0

  • everything is fresh -> return -1, impossible to rot

    [!tip] update the value in place vs. in queue Update in place, such as

    if (grid[a + 1][b] != 0) {
    	queue.push({a, b});
    	grid[a + 1][b] = 0;
    }
    

    Can avoid multiple enqueues, because the value is already updated, so another node in queue can't push that again.

    grid[a][b] = 0;
    if (grid[a + 1][b] != 0) {
    	queue.push({a, b});
    }
    

    this code might result in pushing the same node twice.

Solution

class Solution {
public:
int orangesRotting(vector<vector<int>> &grid) {
  // BFS
  queue<pair<int, int>> todo;
  int m = grid.size(), n = grid[0].size();
  int time = -1;
  bool isGridEmpty = true;
  int freshCount = 0;

  for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
      if (grid[i][j] == 2) {
        // add to queue, rotten
        todo.push({i, j});
      } else if (grid[i][j] == 1) {
        freshCount++;
      }
      if (isGridEmpty && grid[i][j] != 0) {
        isGridEmpty = false;
      }
    }
  }

  int x, y;
  int offset[] = {-1, 1};
  int newX, newY;

  // if there is no value, there's no orange -> no fresh orange
  if (isGridEmpty) {
    return 0;
  }

  while (!todo.empty()) {
    for (int i = 0, size = todo.size(); i < size; i++) {
      x = todo.front().first;
      y = todo.front().second;
      todo.pop();

      for (int o : offset) {
        newX = x + o;
        if (newX >= 0 && newX < m && grid[newX][y] == 1) {
          todo.push({newX, y});
          // cout<<"Pushed: "<<newX<<", "<<y<<'\n';
          grid[newX][y] = 2;
          freshCount--;
        }
        newY = y + o;
        if (newY >= 0 && newY < n && grid[x][newY] == 1) {
          todo.push({x, newY});
          // cout<<"Pushed: "<<x<<", "<<newY<<'\n';
          grid[x][newY] = 2;
          freshCount--;
        }
      }
    }
    time++;
  }

  // check again if there is a fresh orange
  if (freshCount != 0) {
    return -1;
  }

  return time;
}
};