广度优先遍历 总结

1.二叉树的层次遍历

给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

实现

  1.  判断根节点是否为NULL,如果是,直接返回空。

  2. 将根节点插入到队列中,遍历整个队列。

  3. 队列的顶部元素出队,存储其值。

  4. 判断左右节点是否为空,如果不为空,则将其入队。

  5. 重复步骤3.

注意:需要记得队列中现目前的元素数量

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode* >q;  
        if(root==NULL)
            return res;
         q.push(root);
         while(!q.empty())
         {
             vector<int> ans;
             int size=q.size();
             for(int i=0;i<size;i++)
             {
                auto p=q.front();
                q.pop();
                ans.push_back(p->val);
                
                if(p->left!=NULL)
                {
                    q.push(p->left);
                }
                if(p->right!=NULL)
                {
                    q.push(p->right);
                }
             }
             res.push_back(ans);
             ans.clear();

         }   
         return res;

    }
};

2.腐烂的橘子(leetcode 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

 实现

  1. 找出初始腐烂橘子的位置,插入到队列中。
  2. 判断队列是否为空,如果不为空,队列的顶部元素出队,对上、下、左、右四个方向的橘子进行腐烂操作,腐烂的橘子置为2。注意:需要在边界处判断是否越界。
  3. 新的腐烂橘子插入到队列中,重复2。
  4. 然后再次遍历整个区域,判断是否把所有的橘子都腐烂了。
class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {

        int rows=grid.size();
        int cols=grid[0].size();
        std::queue<std::pair<int,int>> orange;
        for(int i=0;i<rows;i++)
        {
            for(int j=0;j<cols;j++)
            {
                if(grid[i][j]==2)
                    orange.push({i,j});
            }
        }
        int time=0;
        while (!orange.empty())
        {
            int size=orange.size();
            bool flag= false;
            for(int i=0;i<size;i++)
            {
                std::pair<int,int> temp=orange.front();
                int row=temp.first;
                int col=temp.second;


                orange.pop();

                if(col+1<cols&&grid[row][col+1]==1)
                {
                    flag= true;
                    grid[row][col+1]=2;
                    orange.push({row,col+1});
                }
                if(col-1>=0&&grid[row][col-1]==1)
                {
                    flag= true;
                    grid[row][col-1]=2;
                    orange.push({row,col-1});
                }
                if(row+1<rows&&grid[row+1][col]==1)
                {
                    flag= true;
                    grid[row+1][col]=2;
                    orange.push({row+1,col});
                }
                if(row-1>=0&&grid[row-1][col]==1)
                {
                    flag= true;
                    grid[row-1][col]=2;
                    orange.push({row-1,col});
                }
            }

            if(flag)
                time++;
        }
        
        for(int i=0;i<rows;i++)
        {
            for(int j=0;j<cols;j++)
            {
                if(grid[i][j]==1)
                    return -1;
            }
        }
        return time;    
        
    }
 
    
};

3.水壶问题(leetcode 365)

  • 日期:2020/3/21

有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?

如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。

你允许:

  • 装满任意一个水壶
  • 清空任意一个水壶
  • 从一个水壶向另外一个水壶倒水,直到装满或者倒空

示例 1: (From the famous "Die Hard" example)

输入: x = 3, y = 5, z = 4
输出: True

示例 2:

输入: x = 2, y = 6, z = 5
输出: False
  •  补充学习知识:std::unordered_set自定义函数

参考:STL: unordered_map 自定义键值类型的使用(C++)

以 x = 1, y = 3, z = 2 为例,一共有八种状态:(0,0), (1,0),(0,1), (1,1),(0,2), (1,2),(0,3), (1,3)。可以以这八种状态构建如下的图:

倒水问题构图.png

  • 节点表示两个水壶的状态
  • 边表示操作方法:分别为倒满A/B,倒空A/B,A倒入B,B倒入A 六种方法。
  • 这是一个有向图,因为有些状态并不能护互为转移。比如 (1,1) 和 (1,0)。

广度优先搜索(BFS):该过程总是从一个或若干个起始点开始,沿着边像水波一样逐层向外遍历,直到所有的点已被访问或者到达目标状态

实现

1.初始时,队列和set均为空。将起始点放入队列及set。

2.如果队列为则 bfs 结束。

3.弹出队首元素并访问其周围元素,设为 p。

4.如果p为目标状态则 bfs 结束。

5. p 执行6种操作,将不在set中的元素放入队列及set。跳转第 2 步。

class Solution {
public:
    pair<int,int> op(int type,pair<int,int> &state,int x,int y)
    {
        switch(type)
        {
            case 0:
                return make_pair(x,state.second);
            case 1:
                return make_pair(state.first,y);
            case 2:
                return make_pair(0,state.second);
            case 3:
                return make_pair(state.first,0);
            case 4:
            {
                int move = min(state.first, y-state.second);
                return make_pair(state.first - move, state.second + move);
            }
            case 5:
            {
                int move = min(x-state.first, state.second);
                return make_pair(state.first + move, state.second - move);
            }
        }
        return make_pair(0,0);
    }
    struct HashPair {
        size_t operator()(const pair<int, int> &key) const noexcept
        {
                return size_t(key.first)*100000007 + key.second;
        }
    };
    bool canMeasureWater(int x, int y, int z) {
        unordered_set<pair<int,int>,HashPair> s;
        queue<pair<int,int>> q;
        q.push({0,0});
        while(!q.empty())
        {
            auto p=q.front();
            q.pop();
            if(p.first+p.second==z)
                return true;
            for(int i=0;i<6;i++)
            {
                auto points=op(i,p,x,y);
                if(s.find(points)!=s.end())
                    continue;
                s.insert(points);
                q.push(points);

            }
        }
        return false;

    }
};
发布了44 篇原创文章 · 获赞 26 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/He3he3he/article/details/105004931
今日推荐