// recursive DFS to detect cycles public boolean hasCycle() { // firstly check if this node is a visited clean node // this pre-check will avoid repeat search and save time if (cleanNode) { return false; } // if our curr node is a visited node, then it means we got a back edge in current path, so // there is a cycle if (visited) { return true; } // mark visited in current search visited = true; // check its neighbor nodes for (Node node : nodes) { // recursivly search each next node if (node.hasCycle()) { return true; } } // reset node as unvisited to avoid the impact on next search visited = false; // if there is no cycle in this node, we will set it as cleanNode cleanNode = true; return false; }
private boolean hasCycle(StringBuilder sb) { // we need put the root node first. To be convenient we want start DFS from any node, not the // node // without prerequisites or with most prerequisites. So we will build the string backward. // We will start build the string after we reach the bottom (the root node). Therefore, in DFS // we should use "depends on" relation, where we put root node to the bottom // cleanNode check first, so we can set and reset "visited" freely if (cleanNode) return false; if (visited) return true; visited = true; for (Node node : nodes) { if (node.hasCycle(sb)) return true; } cleanNode = true; visited = false; sb.append(c); return false; }
public boolean canFinish(int numCourses, int[][] prerequisites) { // create a node list, so we can visit node easier Node[] nodes = new Node[numCourses]; // initialize each node for (int i = 0; i < nodes.length; i++) { nodes[i] = new Node(); } // update neighbors of each node for (int[] pair : prerequisites) { nodes[pair[0]].addNode(nodes[pair[1]]); } // scan array to check if there is any cycle for (Node node : nodes) { if (node.hasCycle()) return false; } return true; }