Created
May 17, 2020 23:07
-
-
Save shixiaoyu/03d0778daf4ad7f21deaffcad3ecb694 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a DFS solution, basically just like detecting if a graph has loops. | |
// Used a lookup table prune, with lookup, this is O(V + E), same as BFS since each node is visited once and only once | |
public boolean canFinish(int numCourses, int[][] prerequisites) { | |
if (numCourses <= 1 || prerequisites.length == 0 || prerequisites[0].length == 0) { | |
return true; | |
} | |
// this is adjacency list, used a set to dedup | |
Map<Integer, Set<Integer>> graph = new HashMap<>(); | |
for (int i = 0; i < numCourses; i++) { | |
graph.put(i, new HashSet<>()); | |
} | |
for (int i = 0; i < prerequisites.length; i++) { | |
graph.get(prerequisites[i][0]).add(prerequisites[i][1]); | |
} | |
Map<Integer, Boolean> lookup = new HashMap<>(); | |
boolean[] visited = new boolean[numCourses]; | |
for (int i = 0; i < numCourses; i++) { | |
if (!this.explore(i, graph, visited, lookup)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
// This is the DFS way to solve it, This could also generate a topological order, think about post order way | |
// return false if there is a loop, true if no loop | |
private boolean explore(int vertex, Map<Integer, Set<Integer>> graph, boolean[] visited, Map<Integer, Boolean> lookup) { | |
// keeps track of if the node has been visited or not, | |
// with this lookup, it's pruning (memorization so that we don't need to re-calculate previously visited node) | |
/* | |
1 | |
/ \ | |
0 3 - 4 | |
\ 2 / | |
e.g., when recursion 0 -> 1 -> 3 -> 4 | |
in 2nd round, 0 -> 2 -> 3(could directly return) | |
*/ | |
if (lookup.containsKey(vertex)) { | |
return lookup.get(vertex); | |
} | |
visited[vertex] = true; // keeps track of visited or not during recursion | |
Set<Integer> dependencies = graph.get(vertex); | |
for (Integer i : dependencies) { | |
if (visited[i] || !this.explore(i, graph, visited, lookup)) { | |
return false; | |
} | |
} | |
visited[vertex] = false; | |
lookup.put(vertex, true); | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment