📜  腐烂所有橙子所需的最短时间

📅  最后修改于: 2022-05-13 01:57:00.967000             🧑  作者: Mango

腐烂所有橙子所需的最短时间

给定一个维度为 m*n 的矩阵,其中矩阵中的每个单元格的值可以为 0、1 或 2,其含义如下:

0: Empty cell
1: Cells have fresh oranges
2: Cells have rotten oranges

确定使所有橙子腐烂所需的最短时间是多少。索引 [i,j] 处的烂橙可以腐烂索引 [i-1,j]、[i+1,j]、[i,j-1]、[i,j+1](向上,下,左,右)。如果不可能腐烂每个橙子,那么只需返回 -1。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。

例子:



Input:  arr[][C] = { {2, 1, 0, 2, 1},
                     {1, 0, 1, 2, 1},
                     {1, 0, 0, 2, 1}};
Output:
All oranges can become rotten in 2-time frames.
Explanation: 
At 0th time frame:
 {2, 1, 0, 2, 1}
 {1, 0, 1, 2, 1}
 {1, 0, 0, 2, 1}

At 1st time frame:
 {2, 2, 0, 2, 2}
 {2, 0, 2, 2, 2}
 {1, 0, 0, 2, 2}

At 2nd time frame:
 {2, 2, 0, 2, 2}
 {2, 0, 2, 2, 2}
 {2, 0, 0, 2, 2}


Input:  arr[][C] = { {2, 1, 0, 2, 1},
                     {0, 0, 1, 2, 1},
                     {1, 0, 0, 2, 1}};
Output:
All oranges cannot be rotten.
Explanation: 
At 0th time frame:
{2, 1, 0, 2, 1}
{0, 0, 1, 2, 1}
{1, 0, 0, 2, 1}

At 1st time frame:
{2, 2, 0, 2, 2}
{0, 0, 2, 2, 2}
{1, 0, 0, 2, 2}

At 2nd time frame:
{2, 2, 0, 2, 2}
{0, 0, 2, 2, 2}
{1, 0, 0, 2, 2}
...
The 1 at the bottom left corner of the matrix is never rotten.

天真的解决方案:

  • 方法:这个想法非常基本。在多轮中遍历所有橙子。在每一轮中,将橙子腐烂到上一轮腐烂的橙子的相邻位置。
  • 算法:
    1. 创建一个变量no = 2changed = false
    2. 运行一个循环,直到在迭代中没有改变矩阵的单元格。
    3. 运行嵌套循环并遍历矩阵。如果矩阵的元素等于no ,则如果相邻元素的值等于1,即未腐烂,则将相邻元素分配给no + 1,并且更新更改为true。
    4. 遍历矩阵并检查是否存在任何为 1 的单元格。如果存在 1,则返回 -1
    5. 否则返回号 – 2
  • 执行:
C++14
// C++ program to rot all oranges when u can move
// in all the four direction from a rotten orange
#include 
using namespace std;
 
const int R = 3;
const int C = 5;
 
// Check if i, j is under the array limits of row and column
bool issafe(int i, int j)
{
    if (i >= 0 && i < R && j >= 0 && j < C)
        return true;
    return false;
}
 
int rotOranges(int v[R][C])
{
    bool changed = false;
    int no = 2;
    while (true) {
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
 
                // Rot all other oranges present at
                // (i+1, j), (i, j-1), (i, j+1), (i-1, j)
                if (v[i][j] == no) {
                    if (issafe(i + 1, j) && v[i + 1][j] == 1) {
                        v[i + 1][j] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i, j + 1) && v[i][j + 1] == 1) {
                        v[i][j + 1] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i - 1, j) && v[i - 1][j] == 1) {
                        v[i - 1][j] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i, j - 1) && v[i][j - 1] == 1) {
                        v[i][j - 1] = v[i][j] + 1;
                        changed = true;
                    }
                }
            }
        }
 
        // if no rotten orange found it means all
        // oranges rottened now
        if (!changed)
            break;
        changed = false;
        no++;
    }
 
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
 
            // if any orange is found to be
            // not rotten then ans is not possible
            if (v[i][j] == 1)
                return -1;
        }
    }
 
    // Because initial value for a rotten
    // orange was 2
    return no - 2;
}
 
// Driver function
int main()
{
 
    int v[R][C] = { { 2, 1, 0, 2, 1 },
                    { 1, 0, 1, 2, 1 },
                    { 1, 0, 0, 2, 1 } };
 
    cout << "Max time incurred: " << rotOranges(v);
 
    return 0;
}


Java
// Java program to rot all oranges when u can move
// in all the four direction from a rotten orange
class GFG{
     
static int R = 3;
static int C = 5;
  
// Check if i, j is under the array
// limits of row and column
static boolean issafe(int i, int j)
{
    if (i >= 0 && i < R &&
        j >= 0 && j < C)
        return true;
         
    return false;
}
  
static int rotOranges(int v[][])
{
    boolean changed = false;
    int no = 2;
     
    while (true)
    {
        for(int i = 0; i < R; i++)
        {
            for(int j = 0; j < C; j++)
            {
                 
                // Rot all other oranges present at
                // (i+1, j), (i, j-1), (i, j+1), (i-1, j)
                if (v[i][j] == no)
                {
                    if (issafe(i + 1, j) &&
                             v[i + 1][j] == 1)
                    {
                        v[i + 1][j] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i, j + 1) &&
                             v[i][j + 1] == 1)
                    {
                        v[i][j + 1] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i - 1, j) &&
                             v[i - 1][j] == 1)
                    {
                        v[i - 1][j] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i, j - 1) &&
                             v[i][j - 1] == 1)
                    {
                        v[i][j - 1] = v[i][j] + 1;
                        changed = true;
                    }
                }
            }
        }
  
        // If no rotten orange found it means all
        // oranges rottened now
        if (!changed)
            break;
             
        changed = false;
        no++;
    }
  
    for(int i = 0; i < R; i++)
    {
        for(int j = 0; j < C; j++)
        {
             
            // If any orange is found to be
            // not rotten then ans is not possible
            if (v[i][j] == 1)
                return -1;
        }
    }
  
    // Because initial value for a rotten
    // orange was 2
    return no - 2;
}
 
// Driver Code
public static void main(String[] args)
{
    int v[][] = { { 2, 1, 0, 2, 1 },
                  { 1, 0, 1, 2, 1 },
                  { 1, 0, 0, 2, 1 } };
  
    System.out.println("Max time incurred: " +
                       rotOranges(v));
}
}
 
// This code is contributed by divyesh072019


Python3
# Python3 program to rot all
# oranges when u can move
# in all the four direction
# from a rotten orang
R = 3
C = 5
 
# Check if i, j is under the
# array limits of row and
# column
def issafe(i, j):
 
    if (i >= 0 and i < R and
        j >= 0 and j < C):
        return True
    return False
 
def rotOranges(v):
 
    changed = False
    no = 2
    while (True):
        for i in range(R):
            for j in range(C):
 
                # Rot all other oranges
                # present at (i+1, j),
                # (i, j-1), (i, j+1),
                # (i-1, j)
                if (v[i][j] == no):
                    if (issafe(i + 1, j) and
                        v[i + 1][j] == 1):
                        v[i + 1][j] = v[i][j] + 1
                        changed = True
 
                    if (issafe(i, j + 1) and
                        v[i][j + 1] == 1):
                        v[i][j + 1] = v[i][j] + 1
                        changed = True
 
                    if (issafe(i - 1, j) and
                        v[i - 1][j] == 1):
                        v[i - 1][j] = v[i][j] + 1
                        changed = True
 
                    if (issafe(i, j - 1) and
                        v[i][j - 1] == 1):
                        v[i][j - 1] = v[i][j] + 1
                        changed = True
 
        # if no rotten orange found
        # it means all oranges rottened
        # now
        if (not changed):
           break
        changed = False
        no += 1
 
    for i in range(R):
        for j in range(C):
 
            # if any orange is found
            # to be not rotten then
            # ans is not possible
            if (v[i][j] == 1):
                return -1
 
    # Because initial value
    # for a rotten orange was 2
    return no - 2
 
# Driver function
if __name__ == "__main__":
 
    v = [[2, 1, 0, 2, 1],
         [1, 0, 1, 2, 1],
         [1, 0, 0, 2, 1]]
 
    print("Max time incurred: ",
           rotOranges(v))
 
# This code is contributed by Chitranayal


C#
// C# program to rot all oranges when u can move
// in all the four direction from a rotten orange
using System;
class GFG {
     
    static int R = 3;
    static int C = 5;
      
    // Check if i, j is under the array
   // limits of row and column
    static bool issafe(int i, int j)
    {
        if (i >= 0 && i < R && j >= 0 && j < C)
            return true;
        return false;
    }
      
    static int rotOranges(int[,] v)
    {
        bool changed = false;
        int no = 2;
        while (true) {
            for (int i = 0; i < R; i++) {
                for (int j = 0; j < C; j++) {
      
                    // Rot all other oranges present at
                    // (i+1, j), (i, j-1), (i, j+1), (i-1, j)
                    if (v[i, j] == no) {
                        if (issafe(i + 1, j) && v[i + 1, j] == 1) {
                            v[i + 1, j] = v[i, j] + 1;
                            changed = true;
                        }
                        if (issafe(i, j + 1) && v[i, j + 1] == 1) {
                            v[i, j + 1] = v[i, j] + 1;
                            changed = true;
                        }
                        if (issafe(i - 1, j) && v[i - 1, j] == 1) {
                            v[i - 1, j] = v[i, j] + 1;
                            changed = true;
                        }
                        if (issafe(i, j - 1) && v[i, j - 1] == 1) {
                            v[i, j - 1] = v[i, j] + 1;
                            changed = true;
                        }
                    }
                }
            }
      
            // if no rotten orange found it means all
            // oranges rottened now
            if (!changed)
                break;
            changed = false;
            no++;
        }
      
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
      
                // if any orange is found to be
                // not rotten then ans is not possible
                if (v[i, j] == 1)
                    return -1;
            }
        }
      
        // Because initial value for a rotten
        // orange was 2
        return no - 2;
    }
 
  static void Main() {
       
    int[ , ] v = { { 2, 1, 0, 2, 1 },
                { 1, 0, 1, 2, 1 },
                { 1, 0, 0, 2, 1 } };
  
    Console.Write("Max time incurred: " + rotOranges(v));
  }
}
 
// This code is contributed by divyeshrabadiya07


Javascript


C++
// C++ program to find minimum time required to make all
// oranges rotten
#include
#define R 3
#define C 5
using namespace std;
 
// function to check whether a cell is valid / invalid
bool isvalid(int i, int j)
{
    return (i >= 0 && j >= 0 && i < R && j < C);
}
 
// structure for storing coordinates of the cell
struct ele {
    int x, y;
};
 
// Function to check whether the cell is delimiter
// which is (-1, -1)
bool isdelim(ele temp)
{
    return (temp.x == -1 && temp.y == -1);
}
 
// Function to check whether there is still a fresh
// orange remaining
bool checkall(int arr[][C])
{
    for (int i=0; i Q;
    ele temp;
    int ans = 0;
 
    // Store all the cells having rotten orange in first time frame
    for (int i=0; i " << ans << endl;
    return 0;
}


Java
//Java program to find minimum time required to make all
//oranges rotten
 
import java.util.LinkedList;
import java.util.Queue;
 
public class RotOrange
{
    public final static int R = 3;
    public final static int C = 5;
     
    // structure for storing coordinates of the cell
    static class Ele
    {
        int x = 0;
        int y = 0;
        Ele(int x,int y)
        {
            this.x = x;
            this.y = y;
        }
    }
     
    // function to check whether a cell is valid / invalid
    static boolean isValid(int i, int j)
    {
        return (i >= 0 && j >= 0 && i < R && j < C);
    }
     
 
    // Function to check whether the cell is delimiter
    // which is (-1, -1)
    static boolean isDelim(Ele temp)
    {
        return (temp.x == -1 && temp.y == -1);
    }
     
    // Function to check whether there is still a fresh
    // orange remaining
    static boolean checkAll(int arr[][])
    {
         for (int i=0; i Q=new LinkedList<>();
        Ele temp;
        int ans = 0;
         // Store all the cells having rotten orange in first time frame
        for (int i=0; i < R; i++)
           for (int j=0; j < C; j++)
               if (arr[i][j] == 2)
                   Q.add(new Ele(i,j));
                 
        // Separate these rotten oranges from the oranges which will rotten
        // due the oranges in first time frame using delimiter which is (-1, -1)
        Q.add(new Ele(-1,-1));
         
        // Process the grid while there are rotten oranges in the Queue
        while(!Q.isEmpty())
        {
            // This flag is used to determine whether even a single fresh
            // orange gets rotten due to rotten oranges in the current time
            // frame so we can increase the count of the required time.
            boolean flag = false;
             
            // Process all the rotten oranges in current time frame.
            while(!isDelim(Q.peek()))
            {
                temp = Q.peek();
                 
                // Check right adjacent cell that if it can be rotten
                if(isValid(temp.x+1, temp.y) && arr[temp.x+1][temp.y] == 1)
                {
                    if(!flag)
                    {
                        // if this is the first orange to get rotten, increase
                        // count and set the flag.
                        ans++;
                        flag = true;
                    }
                    // Make the orange rotten
                    arr[temp.x+1][temp.y] = 2;
                     
                    // push the adjacent orange to Queue
                    temp.x++;
                    Q.add(new Ele(temp.x,temp.y));
                     
                    // Move back to current cell
                    temp.x--;
                }
                 
                // Check left adjacent cell that if it can be rotten
                if (isValid(temp.x-1, temp.y) && arr[temp.x-1][temp.y] == 1)
                 {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x-1][temp.y] = 2;
                        temp.x--;
                        Q.add(new Ele(temp.x,temp.y)); // push this cell to Queue
                        temp.x++;
                 }
                 
                // Check top adjacent cell that if it can be rotten
                 if (isValid(temp.x, temp.y+1) && arr[temp.x][temp.y+1] == 1) {
                        if(!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y+1] = 2;
                        temp.y++;
                        Q.add(new Ele(temp.x,temp.y)); // Push this cell to Queue
                        temp.y--;
                    }
                  
                 // Check bottom adjacent cell if it can be rotten
                 if (isValid(temp.x, temp.y-1) && arr[temp.x][temp.y-1] == 1)
                 {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y-1] = 2;
                        temp.y--;
                        Q.add(new Ele(temp.x,temp.y)); // push this cell to Queue
                 }
                 Q.remove();
                  
            }
            // Pop the delimiter
            Q.remove();
             
            // If oranges were rotten in current frame than separate the
            // rotten oranges using delimiter for the next frame for processing.
            if (!Q.isEmpty())
            {
                Q.add(new Ele(-1,-1));
            }
             
            // If Queue was empty than no rotten oranges left to process so exit
        }
         
        // Return -1 if all arranges could not rot, otherwise ans
        return (checkAll(arr))? -1: ans;
         
    }
     
    // Driver program
    public static void main(String[] args)
    {
        int arr[][] = { {2, 1, 0, 2, 1},
                        {1, 0, 1, 2, 1},
                        {1, 0, 0, 2, 1}};
        int ans = rotOranges(arr);
        if(ans == -1)
            System.out.println("All oranges cannot rot");
        else
            System.out.println("Time required for all oranges to rot = " + ans);
    }
 
}
//This code is contributed by Sumit Ghosh


Python3
# Python3 program to find minimum time required to make all
# oranges rotten
from collections import deque
 
# function to check whether a cell is valid / invalid
def isvalid(i, j):
    return (i >= 0 and j >= 0 and i < 3 and j < 5)
 
# Function to check whether the cell is delimiter
# which is (-1, -1)
def isdelim(temp):
    return (temp[0] == -1 and temp[1] == -1)
 
# Function to check whether there is still a fresh
# orange remaining
def checkall(arr):
    for i in range(3):
       for j in range(5):
          if (arr[i][j] == 1):
             return True
    return False
 
# This function finds if it is
# possible to rot all oranges or not.
# If possible, then it returns
# minimum time required to rot all,
# otherwise returns -1
def rotOranges(arr):
   
    # Create a queue of cells
    Q = deque()
    temp = [0, 0]
    ans = 1
 
    # Store all the cells having
    # rotten orange in first time frame
    for i in range(3):
       for j in range(5):
            if (arr[i][j] == 2):
                temp[0]= i
                temp[1] = j
                Q.append([i, j])
 
    # Separate these rotten oranges
    # from the oranges which will rotten
    # due the oranges in first time
    # frame using delimiter which is (-1, -1)
    temp[0] = -1
    temp[1] = -1
    Q.append([-1, -1])
    # print(Q)
 
    # Process the grid while there are
    # rotten oranges in the Queue
    while False:
       
        # This flag is used to determine
        # whether even a single fresh
        # orange gets rotten due to rotten
        # oranges in current time
        # frame so we can increase
        # the count of the required time.
        flag = False
        print(len(Q))
 
        # Process all the rotten
        # oranges in current time frame.
        while not isdelim(Q[0]):
            temp = Q[0]
            print(len(Q))
 
            # Check right adjacent cell that if it can be rotten
            if (isvalid(temp[0] + 1, temp[1]) and arr[temp[0] + 1][temp[1]] == 1):
                 
                # if this is the first orange to get rotten, increase
                # count and set the flag.
                if (not flag):
                    ans, flag =ans + 1, True
 
                # Make the orange rotten
                arr[temp[0] + 1][temp[1]] = 2
 
                # append the adjacent orange to Queue
                temp[0] += 1
                Q.append(temp)
 
                temp[0] -= 1 # Move back to current cell
 
            # Check left adjacent cell that if it can be rotten
            if (isvalid(temp[0] - 1, temp[1]) and arr[temp[0] - 1][temp[1]] == 1):
                if (not flag):
                    ans, flag =ans + 1, True
                arr[temp[0] - 1][temp[1]] = 2
                temp[0] -= 1
                Q.append(temp) # append this cell to Queue
                temp[0] += 1
 
            # Check top adjacent cell that if it can be rotten
            if (isvalid(temp[0], temp[1] + 1) and arr[temp[0]][temp[1] + 1] == 1):
                if (not flag):
                    ans, flag = ans + 1, True
                arr[temp[0]][temp[1] + 1] = 2
                temp[1] += 1
                Q.append(temp) # Push this cell to Queue
                temp[1] -= 1
 
            # Check bottom adjacent cell if it can be rotten
            if (isvalid(temp[0], temp[1] - 1) and arr[temp[0]][temp[1] - 1] == 1):
                if (not flag):
                    ans, flag = ans + 1, True
                arr[temp[0]][temp[1] - 1] = 2
                temp[1] -= 1
                Q.append(temp) # append this cell to Queue
            Q.popleft()
 
        # Pop the delimiter
        Q.popleft()
 
        # If oranges were rotten in
        # current frame than separate the
        # rotten oranges using delimiter
        # for the next frame for processing.
        if (len(Q) == 0):
            temp[0] = -1
            temp[1] = -1
            Q.append(temp)
 
        # If Queue was empty than no rotten oranges left to process so exit
 
    # Return -1 if all arranges could not rot, otherwise return ans.
    return ans + 1 if(checkall(arr)) else -1
 
# Driver program
if __name__ == '__main__':
    arr = [[2, 1, 0, 2, 1],
         [1, 0, 1, 2, 1],
         [1, 0, 0, 2, 1]]
    ans = rotOranges(arr)
    if (ans == -1):
        print("All oranges cannot rotn")
    else:
        print("Time required for all oranges to rot => " , ans)
 
        # This code is contributed by mohit kumar 29


C#
// C# program to find minimum time
// required to make all oranges rotten
using System;
using System.Collections.Generic;
 
class GFG
{
    public const int R = 3;
    public const int C = 5;
 
    // structure for storing
    // coordinates of the cell
    public class Ele
    {
        public int x = 0;
        public int y = 0;
        public Ele(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
 
    // function to check whether a cell
    // is valid / invalid
    public static bool isValid(int i, int j)
    {
        return (i >= 0 && j >= 0 &&
                i < R && j < C);
    }
 
 
    // Function to check whether the cell
    // is delimiter which is (-1, -1)
    public static bool isDelim(Ele temp)
    {
        return (temp.x == -1 && temp.y == -1);
    }
 
    // Function to check whether there
    // is still a fresh orange remaining
    public static bool checkAll(int[][] arr)
    {
        for (int i = 0; i < R; i++)
        {
            for (int j = 0; j < C; j++)
            {
                if (arr[i][j] == 1)
                {
                    return true;
                }
            }
        }
        return false;
    }
 
    // This function finds if it is possible
    // to rot all oranges or not. If possible,
    // then it returns minimum time required
    // to rot all, otherwise returns -1
    public static int rotOranges(int[][] arr)
    {
        // Create a queue of cells
        LinkedList Q = new LinkedList();
        Ele temp;
        int ans = 0;
         
        // Store all the cells having rotten
        // orange in first time frame
        for (int i = 0; i < R; i++)
        {
        for (int j = 0; j < C; j++)
        {
            if (arr[i][j] == 2)
            {
                Q.AddLast(new Ele(i, j));
            }
        }
        }
 
        // Separate these rotten oranges from
        // the oranges which will rotten
        // due the oranges in first time frame
        // using delimiter which is (-1, -1)
        Q.AddLast(new Ele(-1,-1));
 
        // Process the grid while there are
        // rotten oranges in the Queue
        while (Q.Count > 0)
        {
            // This flag is used to determine
            // whether even a single fresh
            // orange gets rotten due to rotten
            // oranges in current time frame so
            // we can increase the count of the
            // required time.
            bool flag = false;
 
            // Process all the rotten oranges
            // in current time frame.
            while (!isDelim(Q.First.Value))
            {
                temp = Q.First.Value;
 
                // Check right adjacent cell that
                // if it can be rotten
                if (isValid(temp.x + 1, temp.y) &&
                        arr[temp.x + 1][temp.y] == 1)
                {
                    if (!flag)
                    {
                        // if this is the first orange
                        // to get rotten, increase
                        // count and set the flag.
                        ans++;
                        flag = true;
                    }
                     
                    // Make the orange rotten
                    arr[temp.x + 1][temp.y] = 2;
 
                    // push the adjacent orange to Queue
                    temp.x++;
                    Q.AddLast(new Ele(temp.x,temp.y));
 
                    // Move back to current cell
                    temp.x--;
                }
 
                // Check left adjacent cell that
                // if it can be rotten
                if (isValid(temp.x - 1, temp.y) &&
                        arr[temp.x - 1][temp.y] == 1)
                {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x - 1][temp.y] = 2;
                        temp.x--;
                         
                        // push this cell to Queue
                        Q.AddLast(new Ele(temp.x,temp.y));
                        temp.x++;
                }
 
                // Check top adjacent cell that
                // if it can be rotten
                if (isValid(temp.x, temp.y + 1) &&
                        arr[temp.x][temp.y + 1] == 1)
                {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y + 1] = 2;
                        temp.y++;
                         
                        // Push this cell to Queue
                        Q.AddLast(new Ele(temp.x,temp.y));
                        temp.y--;
                }
 
                // Check bottom adjacent cell
                // if it can be rotten
                if (isValid(temp.x, temp.y - 1) &&
                        arr[temp.x][temp.y - 1] == 1)
                {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y - 1] = 2;
                        temp.y--;
                         
                        // push this cell to Queue
                        Q.AddLast(new Ele(temp.x,temp.y));
                }
                Q.RemoveFirst();
 
            }
             
            // Pop the delimiter
            Q.RemoveFirst();
 
            // If oranges were rotten in current
            // frame than separate the rotten
            // oranges using delimiter for the
            // next frame for processing.
            if (Q.Count > 0)
            {
                Q.AddLast(new Ele(-1,-1));
            }
 
            // If Queue was empty than no rotten
            // oranges left to process so exit
        }
 
        // Return -1 if all arranges could
        // not rot, otherwise ans
        return (checkAll(arr)) ? -1: ans;
 
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        int[][] arr = new int[][]
        {
            new int[] {2, 1, 0, 2, 1},
            new int[] {1, 0, 1, 2, 1},
            new int[] {1, 0, 0, 2, 1}
        };
         
        int ans = rotOranges(arr);
        if (ans == -1)
        {
            Console.WriteLine("All oranges cannot rot");
        }
        else
        {
            Console.WriteLine("Time required for all " +
                              "oranges to rot => " + ans);
        }
    }
}
 
// This code is contributed by Shrikant13


输出:
Max time incurred: 2

  • 复杂度分析:
    • 时间复杂度:O((R*C) * (R *C))。
      矩阵需要一次又一次地遍历,直到矩阵没有变化,这可能发生 max(R *C)/2 次。所以时间复杂度是 O((R * C) * (R *C))。
    • 空间复杂度: O(1)。
      不需要额外的空间。

高效的解决方案

  • 方法:这个想法是使用广度优先搜索。橙子腐烂的条件是当它们与其他腐烂的橙子接触时。这类似于广度优先搜索,其中图被划分为层或圆圈,并且搜索是从较低或较近的层到较深或较高的层进行的。在之前的方法中,想法是基于 BFS,但实施效果不佳且效率低下。为了找到值不是整个矩阵的元素,必须遍历整个矩阵。因此可以通过使用这种有效的 BFS 方法来减少时间。
  • 算法:
    1. 创建一个空队列Q
      1. 找到所有腐烂的橙子并将它们排入 Q。此外,排入一个分隔符以指示下一个时间范围的开始。
      2. 运行一个循环 While Q 不为空
      3. 在未达到 Q 中的分隔符时执行以下操作
    2. 从队列中取出一个橙子,腐烂所有相邻的橙子。在腐烂相邻的同时,确保时间范围只增加一次。如果没有相邻的橙子,时间范围不会增加。
    3. 将旧的分隔符出列,并将新的分隔符入列。在前一个时间范围内腐烂的橙子位于两个分隔符之间。
  • 上述方法的试运行:

  • 执行:

C++

// C++ program to find minimum time required to make all
// oranges rotten
#include
#define R 3
#define C 5
using namespace std;
 
// function to check whether a cell is valid / invalid
bool isvalid(int i, int j)
{
    return (i >= 0 && j >= 0 && i < R && j < C);
}
 
// structure for storing coordinates of the cell
struct ele {
    int x, y;
};
 
// Function to check whether the cell is delimiter
// which is (-1, -1)
bool isdelim(ele temp)
{
    return (temp.x == -1 && temp.y == -1);
}
 
// Function to check whether there is still a fresh
// orange remaining
bool checkall(int arr[][C])
{
    for (int i=0; i Q;
    ele temp;
    int ans = 0;
 
    // Store all the cells having rotten orange in first time frame
    for (int i=0; i " << ans << endl;
    return 0;
}

Java

//Java program to find minimum time required to make all
//oranges rotten
 
import java.util.LinkedList;
import java.util.Queue;
 
public class RotOrange
{
    public final static int R = 3;
    public final static int C = 5;
     
    // structure for storing coordinates of the cell
    static class Ele
    {
        int x = 0;
        int y = 0;
        Ele(int x,int y)
        {
            this.x = x;
            this.y = y;
        }
    }
     
    // function to check whether a cell is valid / invalid
    static boolean isValid(int i, int j)
    {
        return (i >= 0 && j >= 0 && i < R && j < C);
    }
     
 
    // Function to check whether the cell is delimiter
    // which is (-1, -1)
    static boolean isDelim(Ele temp)
    {
        return (temp.x == -1 && temp.y == -1);
    }
     
    // Function to check whether there is still a fresh
    // orange remaining
    static boolean checkAll(int arr[][])
    {
         for (int i=0; i Q=new LinkedList<>();
        Ele temp;
        int ans = 0;
         // Store all the cells having rotten orange in first time frame
        for (int i=0; i < R; i++)
           for (int j=0; j < C; j++)
               if (arr[i][j] == 2)
                   Q.add(new Ele(i,j));
                 
        // Separate these rotten oranges from the oranges which will rotten
        // due the oranges in first time frame using delimiter which is (-1, -1)
        Q.add(new Ele(-1,-1));
         
        // Process the grid while there are rotten oranges in the Queue
        while(!Q.isEmpty())
        {
            // This flag is used to determine whether even a single fresh
            // orange gets rotten due to rotten oranges in the current time
            // frame so we can increase the count of the required time.
            boolean flag = false;
             
            // Process all the rotten oranges in current time frame.
            while(!isDelim(Q.peek()))
            {
                temp = Q.peek();
                 
                // Check right adjacent cell that if it can be rotten
                if(isValid(temp.x+1, temp.y) && arr[temp.x+1][temp.y] == 1)
                {
                    if(!flag)
                    {
                        // if this is the first orange to get rotten, increase
                        // count and set the flag.
                        ans++;
                        flag = true;
                    }
                    // Make the orange rotten
                    arr[temp.x+1][temp.y] = 2;
                     
                    // push the adjacent orange to Queue
                    temp.x++;
                    Q.add(new Ele(temp.x,temp.y));
                     
                    // Move back to current cell
                    temp.x--;
                }
                 
                // Check left adjacent cell that if it can be rotten
                if (isValid(temp.x-1, temp.y) && arr[temp.x-1][temp.y] == 1)
                 {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x-1][temp.y] = 2;
                        temp.x--;
                        Q.add(new Ele(temp.x,temp.y)); // push this cell to Queue
                        temp.x++;
                 }
                 
                // Check top adjacent cell that if it can be rotten
                 if (isValid(temp.x, temp.y+1) && arr[temp.x][temp.y+1] == 1) {
                        if(!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y+1] = 2;
                        temp.y++;
                        Q.add(new Ele(temp.x,temp.y)); // Push this cell to Queue
                        temp.y--;
                    }
                  
                 // Check bottom adjacent cell if it can be rotten
                 if (isValid(temp.x, temp.y-1) && arr[temp.x][temp.y-1] == 1)
                 {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y-1] = 2;
                        temp.y--;
                        Q.add(new Ele(temp.x,temp.y)); // push this cell to Queue
                 }
                 Q.remove();
                  
            }
            // Pop the delimiter
            Q.remove();
             
            // If oranges were rotten in current frame than separate the
            // rotten oranges using delimiter for the next frame for processing.
            if (!Q.isEmpty())
            {
                Q.add(new Ele(-1,-1));
            }
             
            // If Queue was empty than no rotten oranges left to process so exit
        }
         
        // Return -1 if all arranges could not rot, otherwise ans
        return (checkAll(arr))? -1: ans;
         
    }
     
    // Driver program
    public static void main(String[] args)
    {
        int arr[][] = { {2, 1, 0, 2, 1},
                        {1, 0, 1, 2, 1},
                        {1, 0, 0, 2, 1}};
        int ans = rotOranges(arr);
        if(ans == -1)
            System.out.println("All oranges cannot rot");
        else
            System.out.println("Time required for all oranges to rot = " + ans);
    }
 
}
//This code is contributed by Sumit Ghosh

蟒蛇3

# Python3 program to find minimum time required to make all
# oranges rotten
from collections import deque
 
# function to check whether a cell is valid / invalid
def isvalid(i, j):
    return (i >= 0 and j >= 0 and i < 3 and j < 5)
 
# Function to check whether the cell is delimiter
# which is (-1, -1)
def isdelim(temp):
    return (temp[0] == -1 and temp[1] == -1)
 
# Function to check whether there is still a fresh
# orange remaining
def checkall(arr):
    for i in range(3):
       for j in range(5):
          if (arr[i][j] == 1):
             return True
    return False
 
# This function finds if it is
# possible to rot all oranges or not.
# If possible, then it returns
# minimum time required to rot all,
# otherwise returns -1
def rotOranges(arr):
   
    # Create a queue of cells
    Q = deque()
    temp = [0, 0]
    ans = 1
 
    # Store all the cells having
    # rotten orange in first time frame
    for i in range(3):
       for j in range(5):
            if (arr[i][j] == 2):
                temp[0]= i
                temp[1] = j
                Q.append([i, j])
 
    # Separate these rotten oranges
    # from the oranges which will rotten
    # due the oranges in first time
    # frame using delimiter which is (-1, -1)
    temp[0] = -1
    temp[1] = -1
    Q.append([-1, -1])
    # print(Q)
 
    # Process the grid while there are
    # rotten oranges in the Queue
    while False:
       
        # This flag is used to determine
        # whether even a single fresh
        # orange gets rotten due to rotten
        # oranges in current time
        # frame so we can increase
        # the count of the required time.
        flag = False
        print(len(Q))
 
        # Process all the rotten
        # oranges in current time frame.
        while not isdelim(Q[0]):
            temp = Q[0]
            print(len(Q))
 
            # Check right adjacent cell that if it can be rotten
            if (isvalid(temp[0] + 1, temp[1]) and arr[temp[0] + 1][temp[1]] == 1):
                 
                # if this is the first orange to get rotten, increase
                # count and set the flag.
                if (not flag):
                    ans, flag =ans + 1, True
 
                # Make the orange rotten
                arr[temp[0] + 1][temp[1]] = 2
 
                # append the adjacent orange to Queue
                temp[0] += 1
                Q.append(temp)
 
                temp[0] -= 1 # Move back to current cell
 
            # Check left adjacent cell that if it can be rotten
            if (isvalid(temp[0] - 1, temp[1]) and arr[temp[0] - 1][temp[1]] == 1):
                if (not flag):
                    ans, flag =ans + 1, True
                arr[temp[0] - 1][temp[1]] = 2
                temp[0] -= 1
                Q.append(temp) # append this cell to Queue
                temp[0] += 1
 
            # Check top adjacent cell that if it can be rotten
            if (isvalid(temp[0], temp[1] + 1) and arr[temp[0]][temp[1] + 1] == 1):
                if (not flag):
                    ans, flag = ans + 1, True
                arr[temp[0]][temp[1] + 1] = 2
                temp[1] += 1
                Q.append(temp) # Push this cell to Queue
                temp[1] -= 1
 
            # Check bottom adjacent cell if it can be rotten
            if (isvalid(temp[0], temp[1] - 1) and arr[temp[0]][temp[1] - 1] == 1):
                if (not flag):
                    ans, flag = ans + 1, True
                arr[temp[0]][temp[1] - 1] = 2
                temp[1] -= 1
                Q.append(temp) # append this cell to Queue
            Q.popleft()
 
        # Pop the delimiter
        Q.popleft()
 
        # If oranges were rotten in
        # current frame than separate the
        # rotten oranges using delimiter
        # for the next frame for processing.
        if (len(Q) == 0):
            temp[0] = -1
            temp[1] = -1
            Q.append(temp)
 
        # If Queue was empty than no rotten oranges left to process so exit
 
    # Return -1 if all arranges could not rot, otherwise return ans.
    return ans + 1 if(checkall(arr)) else -1
 
# Driver program
if __name__ == '__main__':
    arr = [[2, 1, 0, 2, 1],
         [1, 0, 1, 2, 1],
         [1, 0, 0, 2, 1]]
    ans = rotOranges(arr)
    if (ans == -1):
        print("All oranges cannot rotn")
    else:
        print("Time required for all oranges to rot => " , ans)
 
        # This code is contributed by mohit kumar 29

C#

// C# program to find minimum time
// required to make all oranges rotten
using System;
using System.Collections.Generic;
 
class GFG
{
    public const int R = 3;
    public const int C = 5;
 
    // structure for storing
    // coordinates of the cell
    public class Ele
    {
        public int x = 0;
        public int y = 0;
        public Ele(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
 
    // function to check whether a cell
    // is valid / invalid
    public static bool isValid(int i, int j)
    {
        return (i >= 0 && j >= 0 &&
                i < R && j < C);
    }
 
 
    // Function to check whether the cell
    // is delimiter which is (-1, -1)
    public static bool isDelim(Ele temp)
    {
        return (temp.x == -1 && temp.y == -1);
    }
 
    // Function to check whether there
    // is still a fresh orange remaining
    public static bool checkAll(int[][] arr)
    {
        for (int i = 0; i < R; i++)
        {
            for (int j = 0; j < C; j++)
            {
                if (arr[i][j] == 1)
                {
                    return true;
                }
            }
        }
        return false;
    }
 
    // This function finds if it is possible
    // to rot all oranges or not. If possible,
    // then it returns minimum time required
    // to rot all, otherwise returns -1
    public static int rotOranges(int[][] arr)
    {
        // Create a queue of cells
        LinkedList Q = new LinkedList();
        Ele temp;
        int ans = 0;
         
        // Store all the cells having rotten
        // orange in first time frame
        for (int i = 0; i < R; i++)
        {
        for (int j = 0; j < C; j++)
        {
            if (arr[i][j] == 2)
            {
                Q.AddLast(new Ele(i, j));
            }
        }
        }
 
        // Separate these rotten oranges from
        // the oranges which will rotten
        // due the oranges in first time frame
        // using delimiter which is (-1, -1)
        Q.AddLast(new Ele(-1,-1));
 
        // Process the grid while there are
        // rotten oranges in the Queue
        while (Q.Count > 0)
        {
            // This flag is used to determine
            // whether even a single fresh
            // orange gets rotten due to rotten
            // oranges in current time frame so
            // we can increase the count of the
            // required time.
            bool flag = false;
 
            // Process all the rotten oranges
            // in current time frame.
            while (!isDelim(Q.First.Value))
            {
                temp = Q.First.Value;
 
                // Check right adjacent cell that
                // if it can be rotten
                if (isValid(temp.x + 1, temp.y) &&
                        arr[temp.x + 1][temp.y] == 1)
                {
                    if (!flag)
                    {
                        // if this is the first orange
                        // to get rotten, increase
                        // count and set the flag.
                        ans++;
                        flag = true;
                    }
                     
                    // Make the orange rotten
                    arr[temp.x + 1][temp.y] = 2;
 
                    // push the adjacent orange to Queue
                    temp.x++;
                    Q.AddLast(new Ele(temp.x,temp.y));
 
                    // Move back to current cell
                    temp.x--;
                }
 
                // Check left adjacent cell that
                // if it can be rotten
                if (isValid(temp.x - 1, temp.y) &&
                        arr[temp.x - 1][temp.y] == 1)
                {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x - 1][temp.y] = 2;
                        temp.x--;
                         
                        // push this cell to Queue
                        Q.AddLast(new Ele(temp.x,temp.y));
                        temp.x++;
                }
 
                // Check top adjacent cell that
                // if it can be rotten
                if (isValid(temp.x, temp.y + 1) &&
                        arr[temp.x][temp.y + 1] == 1)
                {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y + 1] = 2;
                        temp.y++;
                         
                        // Push this cell to Queue
                        Q.AddLast(new Ele(temp.x,temp.y));
                        temp.y--;
                }
 
                // Check bottom adjacent cell
                // if it can be rotten
                if (isValid(temp.x, temp.y - 1) &&
                        arr[temp.x][temp.y - 1] == 1)
                {
                        if (!flag)
                        {
                            ans++;
                            flag = true;
                        }
                        arr[temp.x][temp.y - 1] = 2;
                        temp.y--;
                         
                        // push this cell to Queue
                        Q.AddLast(new Ele(temp.x,temp.y));
                }
                Q.RemoveFirst();
 
            }
             
            // Pop the delimiter
            Q.RemoveFirst();
 
            // If oranges were rotten in current
            // frame than separate the rotten
            // oranges using delimiter for the
            // next frame for processing.
            if (Q.Count > 0)
            {
                Q.AddLast(new Ele(-1,-1));
            }
 
            // If Queue was empty than no rotten
            // oranges left to process so exit
        }
 
        // Return -1 if all arranges could
        // not rot, otherwise ans
        return (checkAll(arr)) ? -1: ans;
 
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        int[][] arr = new int[][]
        {
            new int[] {2, 1, 0, 2, 1},
            new int[] {1, 0, 1, 2, 1},
            new int[] {1, 0, 0, 2, 1}
        };
         
        int ans = rotOranges(arr);
        if (ans == -1)
        {
            Console.WriteLine("All oranges cannot rot");
        }
        else
        {
            Console.WriteLine("Time required for all " +
                              "oranges to rot => " + ans);
        }
    }
}
 
// This code is contributed by Shrikant13
输出
Time required for all oranges to rot => 2
  • 复杂度分析:
    • 时间复杂度: O(R*C)。
      矩阵的每个元素只能插入队列一次,因此迭代的上限是 O(R*C),即元素的数量。所以时间复杂度是 O(R *C)。
    • 空间复杂度: O(R*C)。
      将元素存储在队列中需要 O(R*C) 空间。