leetcode994(c++):腐烂的橘子

第一次做这种题,看了题解之后知道原来是使用一种叫“BFS”的方法来解,即广度优先遍历。

个人理解:关于BFS,广度优先遍历,思想很简单,先定义一个队列,心中要有一个树的结构,每次只搜索树的一层,搜索到当前节点就把当前节点的母节点从队列中删除,同时将自己入队,当搜索到最后一层,队列中还有最后一层节点,再做一次循环,没有下一节点了,同时把上一轮(最后一层)的结点释放了,那么搜索就完成了,退出循环。

至于你想在每个节点做什么事情,那就在搜索到该结点的时候做了它,所有结点都做了事情,那么整个算法就结束了。
在这里插入图片描述

针对腐烂的橘子这道题,题目的意思:每分钟每个烂橘子可以把四方向相邻的好橘子变腐烂,多少分钟之后橘子全部腐烂?如果未腐烂,则返回-1。

对于每个单元格,可以有好橘子、烂橘子、空。

我们可以这样理解:

  1. 烂橘子要搞事情了,因为每一分钟烂橘子都要把旁边的橘子搞烂。
  2. 那么不妨把烂橘子当成是结点,刚开始的烂橘子就是首层结点,当在当前节点下面搞事情时,先把自己出队。
  3. 当遍历这一次烂橘子的过程中,有好橘子被搞烂,这些橘子就入队(因为下一分钟他们也要参搞烂别的好橘子)
  4. 遍历一次这些烂橘子,遍历完,分钟数+1,(因为是烂橘子是同时让相邻橘子变烂的)

举个例子:
在这里插入图片描述
c++代码:参考此处

 int orangesRotting(vector<vector<int>>& grid) {
 int min = 0, fresh = 0;
   //方向
   vector<pair<int,int>> direct = {{-1,0},{1,0},{0,-1},{0,1}};
   queue<pair<int,int>> q; //队列
   //遍历所有数,记录未烂橘子的个数以及把烂橘子存入队列
   for(int i = 0; i < grid.size(); i++)
       for(int j = 0; j < grid[0].size(); j++)
           if(grid[i][j] == 1) fresh ++;
           else if(grid[i][j] == 2) q.push({i,j});

    while(!q.empty())  //当队列非空
    {
        //有n个烂橘子
        int n = q.size();
        bool rotten = false;
        //遍历这n个烂橘子
        for(int i = 0; i < n; i++) {
            auto x =q.front();
            q.pop();    //因为上面第一次循环的时候已经把烂橘子入队了,所以这里遍历每个烂橘子时实际上是进行下一个节点的搜索,故出队
            //往x的下一个节点搜索,遍历四个方向
            for (auto cur: direct) {
                int i = x.first + cur.first;
                int j = x.second + cur.second;
                //把范围限制在格子内 妙啊! 同时是1
                if(i >= 0 && i < grid.size() && j>= 0 && j< grid[0].size() && grid[i][j]==1)
                {
                    grid[i][j] = 2;
                    q.push({i,j}); //入队,新烂的橘子
                    fresh -- ;     //fresh的橘子减一
                    rotten = true; //rotten设为1
                }
            }
        }
        //意思就是这一次遍历烂橘子,有把好橘子变坏
        //如果没变坏,说明已经搜索完了,静静等待pop完队列就完事了
        if(rotten) min++;
    }
    return fresh ? -1 : min;
    }
发布了39 篇原创文章 · 获赞 50 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Hanghang_/article/details/104684000