[LintCode] Topological Sorting
Given an directed graph, a topological order of the graph nodes is defined as follow:
- For each directed edge
A -> B
in graph, A must appear before B in the order list. - The first node in the order can be any node in the graph with no nodes direct to it.
Find any topological order for the given graph.
For graph as follow:
The topological order can be:
[0, 1, 2, 3, 4, 5]
[0, 2, 3, 1, 5, 4]
...
Can you do it in both BFS and DFS?
Solution 1. DFS, O(n + m) runtime, O(n) space
Algorithm:
1. for each node that has not been explored, dfs on it. The recursive dfs call stops at sinking vertices that have no outgoing edges. At the beginning of each recursive dfs call, mark the current node as explored; Before exiting each recursive dfs call, push the current graph node to a global stack.
2. After all nodes have been explored, pop the stack and add them to the result list.
Proof of correctness: Sinking vertices in the current subgraph are always pushed to the stack first.
1 /** 2 * Definition for Directed graph. 3 * class DirectedGraphNode { 4 * int label; 5 * ArrayList<DirectedGraphNode> neighbors; 6 * DirectedGraphNode(int x) { label = x; neighbors = new ArrayList<DirectedGraphNode>(); } 7 * }; 8 */ 9 10 public class Solution { 11 public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) { 12 ArrayList<DirectedGraphNode> result = new ArrayList<DirectedGraphNode>(); 13 if(graph == null || graph.size() == 0) 14 { 15 return result; 16 } 17 Stack<DirectedGraphNode> stack = new Stack<DirectedGraphNode>(); 18 HashSet<DirectedGraphNode> visited = new HashSet<DirectedGraphNode>(); 19 for(DirectedGraphNode node : graph) 20 { 21 if(!visited.contains(node)) 22 { 23 topSortHelper(node, visited, stack); 24 } 25 } 26 while(!stack.empty()) 27 { 28 result.add(stack.pop()); 29 } 30 return result; 31 } 32 private void topSortHelper(DirectedGraphNode node, 33 HashSet<DirectedGraphNode> visited, 34 Stack<DirectedGraphNode> stack) 35 { 36 visited.add(node); 37 for(DirectedGraphNode neighbor : node.neighbors) 38 { 39 if(!visited.contains(neighbor)) 40 { 41 topSortHelper(neighbor, visited, stack); 42 } 43 } 44 stack.push(node); 45 } 46 }
Solution 2. BFS, O(n + m) runtime, O(n) space
Algorithm:
1. construct a map that stores the number of incoming edges of each graph node. O(m) runtime
2. add graph nodes that have no incoming edges to the queue and result list. O(n) runtime
3. dequeue nodes from the queue one at a time, and update its neighbors's incoming edges by deducting 1.
4. if a neighbor node's incoming edges number becomes 0, add this neighbor node to the queue and the result list.
5. repeat the steps 3 and 4 until the queue is empty.
1 public class Solution { 2 public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) { 3 ArrayList<DirectedGraphNode> result = new ArrayList<DirectedGraphNode>(); 4 //this hash map stores how many incoming edges each node has. 5 //if a node has 0 incoming edges, then it does not get stored in this hash map 6 HashMap<DirectedGraphNode, Integer> map = new HashMap<DirectedGraphNode, Integer>(); 7 for(DirectedGraphNode node : graph) 8 { 9 for(DirectedGraphNode neighbor : node.neighbors) 10 { 11 if(map.containsKey(neighbor)) 12 { 13 map.put(neighbor, map.get(neighbor) + 1); 14 } 15 else 16 { 17 map.put(neighbor, 1); 18 } 19 } 20 } 21 22 Queue<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>(); 23 //First add all the nodes that only have outgoing edges 24 //the order among these nodes do not matter 25 for(DirectedGraphNode node : graph) 26 { 27 if(!map.containsKey(node)) 28 { 29 queue.offer(node); 30 result.add(node); 31 } 32 } 33 while(!queue.isEmpty()) 34 { 35 //node has been added to the result list, so we need to deduct 1 36 //for node's all neighbors. 37 DirectedGraphNode node = queue.poll(); 38 for(DirectedGraphNode neighbor : node.neighbors) 39 { 40 map.put(neighbor, map.get(neighbor) - 1); 41 //neighbor has no incoming edges in the remaining subgraph 42 if(map.get(neighbor) == 0) 43 { 44 result.add(neighbor); 45 queue.offer(neighbor); 46 } 47 } 48 } 49 return result; 50 } 51 }
Related Problems
Course Schedule
Course Schedule II
Sequence Reconstruction