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; } };