腐烂的橘子(leetcode994)

题目

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

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

每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

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

示例 1:

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

思路

多源广度优先遍历,与一般遍历相比,就只需要先遍历整个图找到多个腐烂的橘子(起点),然后加入队列即可。在腐烂时间问题的处理上:

第一次:(感觉不太好有点绕)

在求腐烂的时间问题上需要注意,若移动到某格,四个方向都不可移动,仍然会造成时间加一,找了好久发现这个地方,可以通过一个flag变量,来标记是否能够移动,能移动的话flag标记为1,四个方向都不能的话标记0,只有在flag为1的情况下,腐烂时间再进行+1。

例如 [ [0,2] ];此时只有一个坏橘子,从坏橘子坐标开始遍历,发现四个方向都不可移动,但是变坏时间却会+1。

第二次:

加了time数据来存储每个坐标的腐烂时间,这样就避免了一些特殊情况的考虑

代码

第一种

class Solution {
public:
    typedef pair<int, int> PII;
    int dx[4] = {0, 1, -1, 0}, dy[4] = {1, 0, 0, -1};
    int ans = 0;
    int cnt = 0;
    int flag = 0;//用来标记四个方向是否能移动
    queue<PII> q;
    bool check(int x, int y, int n, int m) {
        return x >= 0 && y >= 0 && x < n && y < m;
    }
    int orangesRotting(vector<vector<int>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        for(int i = 0;i < n;i++)
            for(int j = 0;j < m;j++)
            {
                if(grid[i][j] == 2)
                    q.push({i,j});
                if(grid[i][j] == 1)
                    cnt++;
            }

        while(!q.empty())
        {
            int size = q.size();
            flag = 0;
            while(size--)
            {
                auto temp = q.front();
                q.pop();
                for(int i = 0;i < 4;i++)
                {
                    int x = temp.first + dx[i];
                    int y = temp.second + dy[i];
                    if(check(x,y,n,m) && grid[x][y] == 1)
                    {
                        grid[x][y] = 2;
                        cnt--;
                        flag = 1;
                        if(!cnt)
                            break;
                        q.push({x,y});
                    }
                }
            }
            if(flag)
                ans++;
        }
        return cnt ? -1 : ans;
    }   
};

第二种

class Solution {
public:
    typedef pair<int, int> PII;
    int dx[4] = {0, 1, -1, 0}, dy[4] = {1, 0, 0, -1};
    int ans = 0;
    int cnt = 0;
    int flag = 0;
    int time[11][11];
    queue<PII> q;
    bool check(int x, int y, int n, int m) {
        return x >= 0 && y >= 0 && x < n && y < m;
    }
    int orangesRotting(vector<vector<int>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        for(int i = 0;i < n;i++)
            for(int j = 0;j < m;j++)
            {
                if(grid[i][j] == 2)
                    q.push({i,j});
                if(grid[i][j] == 1)
                    cnt++;
            }

        while(!q.empty())
        {
            auto temp = q.front();
            q.pop();
            for(int i = 0;i < 4;i++)
            {
                int x = temp.first + dx[i];
                int y = temp.second + dy[i];
                if(check(x,y,n,m) && grid[x][y] == 1)
                {
                    //每次加入新坐标进队列就更新time时间
                    time[x][y] = time[temp.first][temp.second] + 1;
                    grid[x][y] = 2;
                    cnt--;
                    ans = time[x][y];
                    q.push({x,y});
                    if(!cnt) break;
                }
            }
        }
        return cnt ? -1 : ans;
    }   
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值