3.4 腐烂的橘子

题目

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

值 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分钟。
  • 用队列先保存所有烂橘子的坐标,用size代表队列中烂橘子的数量。用good表示好橘子的数量。
  • 将队列中的烂橘子取出,size自减1,将周围的好橘子感染。被好橘子被感染,good减一。被感染的好橘子再放到队列中。当size变为0的时候,说明第一批烂橘子已经感染完了。如果此时队列为空,说明没有好橘子变成烂橘子,则循环可以结束。如果此时队列不为空,则size设置为此时队列的长度,继续循环。
  • 循环结束时,判断好橘子数good是否为0,如果不为0,则返回-1。

代码

class Solution {
private:
    int rows, cols;
public:
    int orangesRotting(vector<vector<int>>& grid) {
        if ( grid.size() == 0 ) return 0;
 
        rows = grid.size();
        cols = grid[0].size();
        vector<vector<int>> pattern = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };

        
        int ans = 0;
        queue<vector<int>> q;
        int goodOranges = 0;    // 好橘子的数量

        // 找到所有腐烂的橘子
        for ( int row = 0; row < rows; ++row ) {
            for ( int col = 0; col < cols; ++col ) {
                if ( grid[row][col] == 2 )
                    q.push( {row, col} );
                else if ( grid[row][col] == 1 )
                    ++goodOranges;

            }
        }

        int size = q.size();    // 0 时刻怀橘子的数量
        while ( !q.empty() ) {
            while ( size-- ) {
                vector<int> pos = q.front();
                q.pop();
                
                for ( auto& vec : pattern ) {
                    int nRow = vec[0] + pos[0];
                    int nCol = vec[1] + pos[1];

                    if ( isValid( nRow, nCol ) && grid[nRow][nCol] == 1 ) {
                        grid[nRow][nCol] = 2;
                        q.push( {nRow, nCol } );
                        --goodOranges;          // 新增一个坏橘子,减少一个好橘子。
                    }
                }
            }

            if ( q.empty() ) break; // 如果q.empty()为空,说明没新增腐烂的橘子

            ++ans; 
            size = q.size();  // 下一时刻坏橘子的数量          

        }

        if ( goodOranges != 0 ) ans = -1;  // 还有好橘子


        return ans;
    }

    bool isValid( int row, int col ) {
        return row >=0 && row < rows && col >=0 && col < cols;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值