994. Rotting Oranges

994. 腐烂的橘子

在给定的网格中,每个单元格可以有以下三个值之一:

  • 值 0 代表空单元格;
  • 值 1 代表新鲜橘子;
  • 值 2 代表腐烂的橘子。

每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1

 

示例 1:

输入:[[2,1,1],[1,1,0],[0,1,1]]
输出:4

示例 2:

输入:[[2,1,1],[0,1,1],[1,0,1]]
输出:-1
解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。

示例 3:

输入:[[0,2]]
输出:0
解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。

 

提示:

  1. 1 <= grid.length <= 10
  2. 1 <= grid[0].length <= 10
  3. grid[i][j] 仅为 01 或 2

解法一

//时间复杂度O(n), 空间复杂度O(n)
class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int minutes = -1, count = 0;
        int m = grid.size(), n = grid[0].size();
        
        queue<pair<int, int>> q1;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(grid[i][j] == 2) q1.push({i, j});
                else if(grid[i][j] == 1) count++;
            }
        }
        if(count == 0) return 0;
        
        while(!q1.empty()) {
            queue<pair<int, int>> q2;
            q2.swap(q1);
            
            while(!q2.empty()) {
                int x = q2.front().first, y = q2.front().second;
                q2.pop();
                
                if(x > 0 && grid[x - 1][y] == 1) {
                    grid[x - 1][y] = 2;
                    count--;
                    q1.push({x - 1, y});
                }
                if(x < m - 1 && grid[x + 1][y] == 1) {
                    grid[x + 1][y] = 2;
                    count--;
                    q1.push({x + 1, y});
                }
                if(y > 0 && grid[x][y - 1] == 1) {
                    grid[x][y - 1] = 2;
                    count--;
                    q1.push({x, y - 1});
                }
                if(y < n - 1 && grid[x][y + 1] == 1) {
                    grid[x][y + 1] = 2;
                    count--;
                    q1.push({x, y + 1});
                }
            }
            minutes++;
        }
        return count == 0 ? minutes : -1;
    }
};

优化版:

//时间复杂度O(n), 空间复杂度O(n)
class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int minutes = -1, count = 0;
        int m = grid.size(), n = grid[0].size();
        const int dx[4] = {-1, 1, 0, 0};
        const int dy[4] = {0, 0, -1, 1};
        
        queue<pair<int, int>> q1;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(grid[i][j] == 2) q1.push({i, j});
                else if(grid[i][j] == 1) count++;
            }
        }
        if(count == 0) return 0;
        
        while(!q1.empty()) {
            queue<pair<int, int>> q2;
            q2.swap(q1);
            
            while(!q2.empty()) {
                pair<int, int> pos = q2.front();
                q2.pop();
                
                for(int i = 0; i < 4; i++) {
                    int x = pos.first + dx[i];
                    int y = pos.second + dy[i];
                    if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) {
                        grid[x][y] = 2;
                        count--;
                        q1.push({x, y});
                    }
                }
            }
            minutes++;
        }
        return count == 0 ? minutes : -1;
    }
};

思路:

图的层序遍历。具体做法是使用两个队列q1和q2,q1记录上(下)一层的结点,q2记录当前层的结点。minutes记录经历的分钟数(深度)。

  1. 首先遍历所有元素,将坏橘子(值为2)的坐标入队q1,同时记下好橘子(值为1)的数量count;
  2. 从q1记录的坏橘子坐标开始,进行层序遍历。在每一层内,将q1元素转移至q2(swap)。对于遍历的每一个元素,判断其上、下、左、右是否有好橘子(值为1),若有就将其感染(令值为2),同时对计数count--,并将新感染的橘子入队q1。
  3. 循环步骤2,在每一层内对时间minutes++,直到q1为空。
  4. 最后判断好橘子是否有剩余(count == 0),若有就返回-1,否则返回minutes。

第一版本的代码分支条件太多,优化版使用了循环,效率可能会更好一些。

2019/08/25 13:51
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值