Skip to content

Commit 6ec234b

Browse files
author
freemanzhang
committed
add detecting cycles in directed/undirected graph
1 parent bbc4e61 commit 6ec234b

File tree

1 file changed

+83
-6
lines changed

1 file changed

+83
-6
lines changed

README.md

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@
109109
- [Graph](#graph)
110110
- [Edge list vs Adjacent list vs Adjacent matrix](#edge-list-vs-adjacent-list-vs-adjacent-matrix)
111111
- [Build graph](#build-graph)
112+
- [Detect cycles inside undirected graph](#detect-cycles-inside-undirected-graph)
113+
- [Detect cycles inside directed graph](#detect-cycles-inside-directed-graph)
112114
- [Trie](#trie)
113115
- [Use case](#use-case-1)
114116
- [Trie definition](#trie-definition)
@@ -169,6 +171,7 @@
169171
- [Memorization array tricks](#memorization-array-tricks)
170172
- [Type](#type)
171173
- [Online IDE templates](#online-ide-templates)
174+
- [Coderpad](#coderpad)
172175
- [References](#references)
173176

174177
<!-- /MarkdownTOC -->
@@ -1827,7 +1830,6 @@ class SegmentTreeNode
18271830
* Validate binary search tree
18281831
- Iterative inorder traversal, current node > successor (stack top). Works for BST with no duplication constraints
18291832
- Divide and conquer, pass down value range in children nodes
1830-
* Kth node in a BST
18311833
18321834
* Generic tree preorder/inorder/postorder iterative traversal with O(logn) space. Three types of implementation could be changed with minimal code change.
18331835
```java
@@ -2200,8 +2202,82 @@ public Map<Integer, Set<Integer>> buildGraph( int n, int[][] edges )
22002202
}
22012203
}
22022204
```
2203-
* **Detect cycles inside undirected graph** with dfs + discovered set.
2204-
* **Detect cycles inside directed graph** with dfs + visited set + discovered set.
2205+
2206+
##### Detect cycles inside undirected graph
2207+
2208+
```java
2209+
// Graph is represented by class GraphNode
2210+
class GraphNode
2211+
{
2212+
int nodeIndex;
2213+
List<GraphNode> neighbors;
2214+
}
2215+
2216+
private boolean hasCycle( GraphNode root )
2217+
{
2218+
return hasCycle( root, new HashSet<>() );
2219+
}
2220+
2221+
private boolean hasCycle( GraphNode root, Set<GraphNode> isDiscovered )
2222+
{
2223+
if ( isDiscovered.contains( root ) )
2224+
{
2225+
return true;
2226+
}
2227+
2228+
isDiscovered.add( root );
2229+
for ( List<GraphNode> neighbor : root.neighbors )
2230+
{
2231+
if ( hasCycle( neighbor, isVisited ) )
2232+
{
2233+
return true;
2234+
}
2235+
}
2236+
2237+
return false;
2238+
}
2239+
```
2240+
2241+
##### Detect cycles inside directed graph
2242+
2243+
```java
2244+
// Graph is represented by class GraphNode
2245+
class GraphNode
2246+
{
2247+
int nodeIndex;
2248+
List<GraphNode> neighbors;
2249+
}
2250+
2251+
private boolean hasCycle( GraphNode root )
2252+
{
2253+
Set<GraphNode> isDiscovered = new HashSet<>();
2254+
Set<GraphNode> isVisited = new HashSet<>();
2255+
return hasCycle( root, isDiscovered, isVisited );
2256+
}
2257+
2258+
private boolean hasCycle( GraphNode root, Set<GraphNode> isDiscovered, Set<GraphNode> isVisited )
2259+
{
2260+
if ( isVisited.contains( root ) )
2261+
{
2262+
return false;
2263+
}
2264+
if ( isDiscovered.contains( root ) && !isVisited.contains( root ) )
2265+
{
2266+
return true;
2267+
}
2268+
2269+
isDiscovered.add( root );
2270+
for ( List<GraphNode> neighbor : root.neighbors )
2271+
{
2272+
if ( hasCycle( neighbor, isDiscovered, isVisited ) )
2273+
{
2274+
return true;
2275+
}
2276+
}
2277+
isVisited.add( root );
2278+
return false;
2279+
}
2280+
```
22052281

22062282
#### Trie
22072283
##### Use case
@@ -2803,6 +2879,7 @@ public int binarySearchRecursive( int[] array, int target, int start, int end )
28032879
+ If multiple results are of same type, define return type as an array T[]
28042880
+ If only two results are returned, consider using AbstractMap.SimpleEntry<K,V>
28052881
+ Define a result wrapper class
2882+
28062883
```java
28072884
// 1. not use use global variables
28082885
// 1.1. global variables as class instance
@@ -2838,6 +2915,7 @@ private class ResultWrapper
28382915

28392916
##### Avoid duplicated recursion
28402917
* ensuring that the never two recursion tree branches overlap
2918+
28412919
```java
28422920
if ( i > 0 && candidates[i] == candidates[i-1] )
28432921
{
@@ -2846,6 +2924,7 @@ if ( i > 0 && candidates[i] == candidates[i-1] )
28462924
}
28472925
// invoking functions based on index i
28482926
```
2927+
28492928
##### Types
28502929

28512930
* Tree-based recursion
@@ -2880,8 +2959,6 @@ public ResultWrapper secondApproach( TreeNode currNode )
28802959
- Key points: Use a hashmap to store old to new reference mapping
28812960
- Examples: Clone graph, Copy list with random pointer
28822961

2883-
* Array-based recursion
2884-
28852962
#### Backtrack
28862963
##### Best practices
28872964
* There are two popular ways to keep track of traverse path
@@ -3349,7 +3426,7 @@ public int houseRobber_RollingArray( int[] A )
33493426
+ Examples: Backpack I-VI (Lintcode), K Sum (Lintcode), Minimum adjustment cost (Lintcode)
33503427

33513428
### Online IDE templates
3352-
* Coderpad
3429+
#### Coderpad
33533430

33543431
```java
33553432
import org.junit.*;

0 commit comments

Comments
 (0)