BFS+邻接表

作者: zhouycoriginal | 来源:发表于2020-01-18 21:41 被阅读0次

All Nodes Distance K in Binary Tree

We are given a binary tree (with root node root), a target node, and an integer value K.
Return a list of the values of all nodes that have a distance K from the target node. The answer can be returned in any order.


image.png
image.png

一二叉树,给一个根结点,和一个目标结点以及一个距离K,要求所以和目标结点相距为K的结点值。根据例子,目标结点5,于其相距为2的结点分别是:7,4,1:也就是连接距离为2。

思路:直接根据二叉树来找结果,在这里有些不好思考,如果把目标结点看作根结点呢?就会发现[2,3,6]是第一层,[1,7,4]刚好是第二层,也就是K。然后这就是一个图的BFS过程,遍历到第K层就可以了
关键在于,如何构建这个图,因为我们知道二叉树只有left,right两个point,而图是有多个孩子的。从这里我们可以构建邻接表,因为我们知道各自结点的孩子结点以及父结点

根据这个图我们可以构建出邻接表:


image.png

上图的邻接表就是这样的,那么剩下的就是 通过 队列+visit数组来寻找结点的过程了。队列先push目标结点,之后相应visit设置为true,当访问到K层时,把结果找出来。我们在此可以用一个map存储邻接表,key为结点,value为其邻居结点。在构建邻接表时,我们可以用二叉树的几种遍历方法实现构建这个表,这里使用先序遍历。

class Solution {
public:

    void build_table(TreeNode *node, TreeNode *parent, unordered_map<TreeNode*,vector<TreeNode*>> &table){
        if(!node) return;
        if(table.count(node)) return;
        if(parent){
            table[node].push_back(parent);
            table[parent].push_back(node);
        }
        build_table(node->left,node,table);
        build_table(node->right,node,table);
    }

    vector<int> distanceK(TreeNode* root, TreeNode* target, int K) {
        unordered_map<TreeNode*,vector<TreeNode*>> table;
        vector<int> res;
        int level = 1;
        build_table(root,NULL,table);
        unordered_set<TreeNode*> visited{{target}};
        queue<TreeNode*> my_queue;
        unordered_map<TreeNode*,bool> visited;
        TreeNode* tmp_node;

        if(!root)
            return res;

        my_queue.push(target);
        my_queue.push(NULL);

        while(!my_queue.empty()){   
            while(my_queue.front()!=NULL){  
                tmp_node = my_queue.front();
                visited[tmp_node] = true;

                if(level==K){
                    for(auto item:table[tmp_node]){
                        if(!visited[item])
                            res.push_back(item->val);
                    }
                }
                for(auto item:table[tmp_node]){
                    if(visited[item])
                        continue;
                    my_queue.push(item);    
                }
                my_queue.pop();
            }
            my_queue.pop();
            level++;
            if(!my_queue.empty())
                my_queue.push(NULL);
            if(level>K)
                return res;
        }
        
        return res;
    }
};

2. Course Schedule

There are a total of n courses you have to take, labeled from 0 to n-1.Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1] Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

image.png
对于本题,我们可以用一个有向图来表示课程之间的选择关系,例如:
在图中,我们用箭头表示依赖关系,图下面的表代表各自结点的入度,在这里也就相当于“选本门课程之前,需要预先完成的课程”。 我们知道选课是不可能有环的,也就是说“选A课程之前必先修B课程,选B之前必先修A课程”,这是矛盾的,也是不可能的,所以题目的主要目的是判断有向图中的是否存在环的问题
判断有向图是否存在环,可以用 拓扑排序 来做。先不提拓扑排序,先看第一个图,以它为例:
我们先
    1. 用邻接表来表示整个图,并同时构造结点的入度向量
    1. 把入度为0的结点入队列
    1. 对队列里的元素进行BFS, 同时对应的结点入度-1,这是BFS的标准操作
  • 4.队列为空后,若入度还存在有大于0的结点,那么第一,这个图存在环,第二,不能完成课程

[图片上传中...(image.png-cef2f9-1579354794344-0)]
比如第一个图 队列pop的结果是 0 1 2 3 4 5 这个序例就是拓扑排序的结果


image.png
class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {

        if(numCourses<0)
            return false;
        if(prerequisites.size()==0)
            return true;

        vector<int> in_degree(numCourses,0);
        map<int, vector<int>> table;
        queue<int> my_queue;

        // generate indegree and linked table
        int rows = prerequisites.size();
        int cols = prerequisites[0].size();
        for(int i=0;i<rows;i++){
            in_degree[prerequisites[i][0]]++;
            int key = prerequisites[i][1];
            int value = prerequisites[i][0];
            if(table.count(key))
                table[key].push_back(value);
            else
                table[key] = {value};
        }
        
        for(int i=0;i<numCourses;i++){
            if(in_degree[i]==0)
                my_queue.push(i);
        }

        while(!my_queue.empty()){
            int tmp_key = my_queue.front();
            for(auto key:table[tmp_key]){
                in_degree[key]--;
                if(in_degree[key]==0)
                    my_queue.push(key);
            }
            my_queue.pop();

        }

        for(auto key:in_degree){
            if(in_degree[key]!=0)
                return false;
        }

        return true;
    }
};

3. Minimum Height Trees

For an undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.
Format
The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels). You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.


image.png

要求找到最小深度的树,每一个结点都有可能是根结点。暴力遍历显然是最简单的,但是不可能通过。因为2个结点互相都是各自的孩子结点,且最后的根结点不可能超过2个。

思路:我们可以从最后一层,也就是结点的度(包括入度和出度为0或者1的结点)开始,往后BFS,相应的对应结点的父亲结点度-1,这样每次BFS,把度为1的点入队,层层筛选,选择最后一层剩下的那1个或者2个结点,且最后一层只可能存在1或2个结点。

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        vector<int> roots;
        map<int, vector<int>> linked_table;
        queue<int> node_queue;
        vector<int> degree(n,0);
        vector<int> visited(n,false);
        // generate linked table;
         if (edges.size() == 0) {
            roots.push_back(0);
            return roots;
        }

        for(auto node:edges){
            degree[node[0]]++;
            degree[node[1]]++;
            linked_table[node[0]].push_back(node[1]);
            linked_table[node[1]].push_back(node[0]);
        }

        // find degree equal to 0 or 1, push them into queue
        for(auto node:edges){
            if((degree[node[0]]==0 || degree[node[0]]==1)&&(!visited[node[0]])){
                node_queue.push(node[0]);
                visited[node[0]] = true;
            }
            if((degree[node[1]]==0 || degree[node[1]]==1)&&(!visited[node[1]])){
                node_queue.push(node[1]);
                visited[node[1]] = true;
            }
        }

        // start looking for
        while(!node_queue.empty()){
            int queue_current_size = node_queue.size();
            roots.clear();//根结点遍历完一层,清空,准备记录下一层的结点
            while(queue_current_size){
                int tmp_node = node_queue.front();
                roots.push_back(tmp_node);

                for(auto link_tmp_node:linked_table[tmp_node]){
                    degree[tmp_node]--;
                    degree[link_tmp_node]--;
                    if(degree[link_tmp_node]==1 || degree[link_tmp_node]==0 && !visited[link_tmp_node]){
                        node_queue.push(link_tmp_node);
                        visited[link_tmp_node] = true;
                    }
                }
                
                node_queue.pop();
                queue_current_size--;
            }
        }

        return roots; 
    }
};

相关文章

  • BFS+邻接表

    All Nodes Distance K in Binary Tree We are given a binary...

  • 2017-5-14 省赛模板

    简介 搜索迷宫(BFS+队列) 最短路Dijkstra+邻接矩阵Dijkstra+链式前向星+优先队列Bellma...

  • Java数据结构 - 图(邻接表存储)

    邻接表 相比邻接矩阵,邻接表要更加节省空间。 邻接表存储 本文将介绍邻接表存储有向带权图。图的例子如下。 介绍一下...

  • 图的表示,golang实现

    邻接表 邻接矩阵

  • 数据结构与算法-图

    邻接矩阵 邻接表

  • 第七章 图

    邻接表定义 邻接表求各点入度 邻接表各点出度 DFS与BFS遍历 已知一个无向图G的邻接表存储表示如下,试写出从顶...

  • 邻接表|SPFA

    邻接表简易定义//定义简易邻接表 SPFA不完整实现

  • 采用BFS遍历图

    伪代码: ①邻接矩阵版: ②邻接表版:

  • 邻接表

    //正确 //现为无向图 //但是一下改成有向图好像有点不对,要琢磨下 #include #include //...

  • 邻接表

    first[u[i]]中保存顶点u[i]的最后一条边的编号,next[i]储存“编号为i的边的下一条边,先将f中的...

网友评论

    本文标题:BFS+邻接表

    本文链接:https://www.haomeiwen.com/subject/vjdlzctx.html