Problem:
In a given grid, each cell can have one of three values:
the value 0 representing an empty cell;
the value 1 representing a fresh orange;
the value 2 representing a rotten orange.
Every minute, any fresh orange that is adjacent (4-directionally) 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 instead. source
Approach:
I am trying to solve this problem in BFS manner. I first push every occurrence of a rotten orange into a queue. Then I go through the grid counting the occurrences of fresh oranges near the rotten ones and set that current position to be a rotten orange.
The problem is that if there is more than one rotten orange, they should be processed "at the same time". But my code currently processes one orange, increments time and then processes the next orange.
Thus for this test case std::vector<std::vector<int>> grid = { {1, 2, 1, 1, 2, 1, 1} };
the result should be 2 and the code prints 3.
Code:
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
int time = 0;
if (grid.empty())
return time;
std::queue<std::pair<int, int>> q;
for (int i = 0; i < grid.size(); ++i)
{
for (int j = 0; j < grid[i].size(); ++j)
{
if (grid[i][j] == 2)
q.push({ i,j });
}
}
std::vector<std::vector<int>> dirs = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
while (!q.empty())
{
int n = q.size();
auto p = q.front();
q.pop();
n--;
for (auto dir : dirs)
{
int row = p.first;
int col = p.second;
if (isValid(grid, row + dir[0], col + dir[1]))
{
row += dir[0];
col += dir[1];
if (n == 0)
{
time++;
n = q.size();
}
q.push({ row, col });
grid[row][col] = 2;
}
}
}
for (int i = 0; i < grid.size(); i++)
{
for (int j = 0; j < grid[i].size(); ++j)
{
if (grid[i][j] == 1)
{
time = -1;
break;
}
}
}
return time;
}
bool isValid(vector<vector<int>>& grid, int i, int j)
{
if (i < 0 || i >= grid.size() || j < 0 || j >= grid[i].size() || grid[i][j] != 1)
return false;
return true;
}
};
int main()
{
Solution obj;
std::vector<std::vector<int>> grid = { {1, 2, 1, 1, 2, 1, 1} };
auto result = obj.orangesRotting(grid);
int correct_solution = 2;
if (result == correct_solution)
std::cout << "Correct!";
else
std::cout << "Not correct!";
std::cin.get();
}
Question:
I am not sure how to deal with the fact that if there is more than one rotten orange, they should be processed "at the same time". Any ideas?
Update:
Attempting the first comments approach:
class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
int time = 0;
if (grid.empty())
return time;
std::queue<std::pair<int, int>> q;
for (int i = 0; i < grid.size(); ++i)
{
for (int j = 0; j < grid[i].size(); ++j)
{
if (grid[i][j] == 2)
q.push({ i,j });
}
}
std::vector<std::vector<int>> dirs = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
while (!q.empty())
{
int n = q.size();
for (int i = 0; i < n; ++i)
{
auto p = q.front();
q.pop();
n--;
for (auto dir : dirs)
{
int row = p.first;
int col = p.second;
if (isValid(grid, row + dir[0], col + dir[1]))
{
row += dir[0];
col += dir[1];
if (n == 0)
{
time++;
}
q.push({ row, col });
grid[row][col] = 2;
}
}
}
}
for (int i = 0; i < grid.size(); i++)
{
for (int j = 0; j < grid[i].size(); ++j)
{
if (grid[i][j] == 1)
{
time = -1;
break;
}
}
}
return time;
}
bool isValid(vector<vector<int>>& grid, int i, int j)
{
if (i < 0 || i >= grid.size() || j < 0 || j >= grid[i].size() || grid[i][j] != 1)
return false;
return true;
}
};