leetcode 207. Course Schedule 、 210. Course Schedule II 、 310. Minimum Height Trees

207. Course Schedule

https://blog.csdn.net/wongleetion/article/details/79433101

问题的实质就是判断一个有向图是否有环,利用入度去解决这个问题

使用bfs解决问题。

初始化时,利用二维vector存储节点间的关系,并存储每个节点的入度,同时将入度为0的节点放入队列,这是图的起始点。

每次将队列中的节点弹出后,然后将对应的课程的入度减少,如果有此时产生入度为0的节点,再加入队列中,直到队列为空。

最终判断整个入度的存储是否还有节点入度不为0。

class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<vector<int>> graph(numCourses,vector<int>(0));
        vector<int> inDegree(numCourses,0);
        for(auto i : prerequisites){
            graph[i.second].push_back(i.first);
            inDegree[i.first]++;
        }
        
        queue<int> q;
        for(int i = 0;i < numCourses;i++){
            if(inDegree[i] == 0)
                q.push(i);
        }
        
        while(!q.empty()){
            int num = q.front();
            q.pop();
            for(auto i : graph[num]){
                inDegree[i]--;
                if(inDegree[i] == 0)
                    q.push(i);
            }
        }
        
        for(int i = 0;i < numCourses;i++){
            if(inDegree[i] != 0)
                return false;
        }
        return true;
    }
};

 

 

210. Course Schedule II

这个题是要你把学习课程的路径求出来,如果有环,就返回空数组。

这个题基本上与Course Schedule代码差不多,只需要每次在queue弹出的时候存入结果就好,还需要判断是否有环。

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> graph(numCourses);
        vector<int> indegree(numCourses);
        vector<int> result;
        for(int i = 0;i < prerequisites.size();i++){
            graph[prerequisites[i][1]].push_back(prerequisites[i][0]);
            indegree[prerequisites[i][0]]++;
        }
        queue<int> q;
        for(int i = 0;i < numCourses;i++){
            if(indegree[i] == 0)
                q.push(i);
        }
        while(!q.empty()){
            int course = q.front();
            q.pop();
            result.push_back(course);
            for(int i = 0;i < graph[course].size();i++){
                indegree[graph[course][i]]--;
                if(indegree[graph[course][i]] == 0)
                    q.push(graph[course][i]);
            }
        }
        vector<int> res;
        for(int i = 0;i < numCourses;i++){
            if(indegree[i] != 0)
                return res;
        }
        return result;
    }
};

 

310. Minimum Height Trees

https://www.cnblogs.com/grandyang/p/5000291.html

给定一个拥有树性质的无向图,图的每一个节点都可以视为一棵树的根节点。在所有可能的树中,找出高度最小的树,并返回他们的树根。

如果剩余的节点数超过两个,就可以继续去除叶节点,比如剩余了3个节点,那么其实可以把外面的两个节点去掉,就只剩一个节点了,而且以这个节点做根,得到的树的高度最小;而如果剩余了2个节点,那么不论让谁当根,得到的高度都是一样的;如果剩余一个,自然不必多说就是根节点了。

我们开始将所有只有一个连接边的节点(叶节点)都存入到一个队列queue中,然后我们遍历每一个叶节点,通过图来找到和其相连的节点,并且在其相连节点的集合中将该叶节点删去,如果删完后此节点也也变成一个叶节点了,加入队列中,再下一轮删除。那么我们删到什么时候呢,当节点数小于等于2时候停止,此时剩下的一个或两个节点就是我们要求的最小高度树的根节点

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        if(n == 1)
            return {0};
        vector<int> res;
        vector<unordered_set<int>> adj(n);
        queue<int> q;
        for(int i = 0;i < edges.size();i++){
            adj[edges[i][0]].insert(edges[i][1]);
            adj[edges[i][1]].insert(edges[i][0]);
        }
        for(int i = 0;i < n;i++){
            if(adj[i].size() == 1)
                q.push(i);
        }
        while(n > 2){
            int size = q.size();
            n -= size;
            for(int i = 0;i < size;i++){
                int tmp = q.front();
                q.pop();
                for(auto j : adj[tmp]){
                    adj[j].erase(tmp);
                    if(adj[j].size() == 1)
                        q.push(j);
                }
            }
        }
        while(!q.empty()){
            int tmp = q.front();
            q.pop();
            res.push_back(tmp);
        }
        return res;
    }
};

 

posted @ 2019-03-13 11:06  有梦就要去实现他  阅读(121)  评论(0编辑  收藏  举报