207. Course Schedule && 210. Course Schedule II && 310. Minimum Height Trees
207. 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?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
- This problem is equivalent to finding if a cycle exists in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
- Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
- Topological sort could also be done via BFS.
Solution:
Easy BFS. Starting points are those who have indegree 0. Iteratively reduce the indegree of connected vertices by 1.
public class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { if(numCourses<=1) return true; //from -> List(to) //out -> List(in) ArrayList<Integer>[] adjacencyList = new ArrayList[numCourses]; for(int i = 0; i<numCourses; ++i) adjacencyList[i] = new ArrayList<Integer>(); int[] indegree = new int[numCourses]; for(int[] prerequesite: prerequisites) { adjacencyList[prerequesite[1]].add(prerequesite[0]); ++indegree[prerequesite[0]]; } //outmostLayer is the layer that we can start with ArrayList<Integer> outmostLayer = new ArrayList<Integer>(); for(int i = 0; i<numCourses; ++i) if(indegree[i]==0) outmostLayer.add(i); while(outmostLayer.size()>0) { ArrayList<Integer> nextLayer = new ArrayList<Integer>(); for(int from: outmostLayer) { for(int to: adjacencyList[from]) { --indegree[to]; if(indegree[to]==0) nextLayer.add(to); } } outmostLayer = nextLayer; } for(int i = 0; i<numCourses; ++i) if(indegree[i]!=0) return false; return true; } }
DFS solution:
import java.lang.reflect.Array; public class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { HashSet<Integer>[] adjacencyList = (HashSet<Integer>[])Array.newInstance(HashSet.class, numCourses); for(int i = 0; i<numCourses; ++i) { adjacencyList[i] = new HashSet<Integer>(); } for(int[] prerequesite: prerequisites) { adjacencyList[prerequesite[1]].add(prerequesite[0]); } int[] visit = new int[numCourses]; //0 means unvisited //1 means visited/good/no cycles //-1 means under current searching path, no determined yet. for(int i = 0; i<numCourses; ++i) { if(!DFS(adjacencyList, i, visit)) return false; } return true; } private boolean DFS(HashSet<Integer>[] adjacencyList, int node, int[] visit) { if(visit[node] == 1) return true; //This node is good. There is no cycles. visit[node] = -1; for(int out: adjacencyList[node]) { if(visit[out]==-1 // equals -1 mean a cycle is made from this node(out). || !DFS(adjacencyList, out, visit)) // means children nodes have cycles. return false; //Found cycles. } visit[node] = 1; //Set visit to 1 when you backtrack, meanning that this node and all children nodes are good. return true; } }
210. Course Schedule II
Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.
public class Solution { public int[] findOrder(int numCourses, int[][] prerequisites) { if(numCourses == 0) return new int[0]; int[] inbounds = new int[numCourses]; List<List<Integer>> outBounds = new ArrayList<List<Integer>>(); for(int i = 0; i<numCourses; ++i) { outBounds.add(new ArrayList<Integer>()); } for(int[] pair: prerequisites) { int from = pair[1]; int to = pair[0]; ++inbounds[to]; List<Integer> outs = outBounds.get(from); outs.add(to); } List<Integer> starts = new ArrayList<Integer>(); for(int i = 0; i<numCourses; ++i) if(inbounds[i] == 0) starts.add(i); int[] ret = new int[numCourses]; int i=0; while(starts.size()>0) { List<Integer> newStarts = new ArrayList<Integer>(); for(Integer start: starts) { ret[i++] = start; for(Integer out: outBounds.get(start)) { --inbounds[out]; if(inbounds[out] == 0) newStarts.add(out); } } starts = newStarts; } for(int n = 0; n<numCourses; ++n) { if(inbounds[n]>0) return new int[0]; } return ret; } }
310. Minimum Height Trees
For a 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.
Example 1:
Given n = 4, edges = [[1, 0], [1, 2], [1, 3]]
0
|
1
/ \
2 3
return [1]
Example 2:
Given n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]
0 1 2
\ | /
3
|
4
|
5
return [3, 4]
Hint: How many MHTs can a graph have at most?
Note:
(1) According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”
(2) The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.
public class Solution { public List<Integer> findMinHeightTrees(int n, int[][] edges) { List<Integer> ret = new ArrayList<Integer>(); if(n == 0) return ret; if(n == 1) { ret.add(0); return ret; } int[] count = new int[n]; List<LinkedList<Integer>> neighbors = new ArrayList<LinkedList<Integer>>(n); for(int i = 0; i<n; ++i) neighbors.add(new LinkedList()); for(int[] edge: edges) { int node1 = edge[0]; int node2 = edge[1]; ++count[node1]; ++count[node2]; neighbors.get(node1).add(node2); neighbors.get(node2).add(node1); } List<Integer> starts = new ArrayList<Integer>(); for(int i = 0; i<n; ++i) if(count[i] == 1) starts.add(i); while(n>2) { List<Integer> newStarts = new ArrayList<Integer>(); for(Integer surfaceNode: starts) { --n; for(Integer innerNode: neighbors.get(surfaceNode)) { --count[innerNode]; if(count[innerNode] == 1) newStarts.add(innerNode); } } starts = newStarts; } return starts; } }

浙公网安备 33010602011771号