lintcode127- Topological Sorting- medium

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 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.
Notice
You can assume that there is at least one topological order in the graph.
Clarification
Learn more about representation of graphs
Example
For graph as follow:
The topological order can be:
[0, 1, 2, 3, 4, 5]
[0, 2, 3, 1, 5, 4]
...
Challenge 
Can you do it in both BFS and DFS?
 
算法:BFS。1.找到每个节点-入度的map。2.queue推入所有入度0的点。3.BFS,取出后对每个点邻居入度-1,减到0邻居入queue(说明解锁了)。
数据结构:Queue(用于BFS),Map(存入度),ArrayList(存顺序的结果)
注意入度为0的点不是让你从每个点开始试一试,而是直接把它们全都推进去。因为最后要所有点都在order里,入度0的点你现在不推以后永远不会有机会推。 
 
算法:DFS。建立HashSet<DirectedGraphNode> visited,标记遍历过的点node。递归dfs函数去遍历nodeneighbors,继续在visited中标记,使得所有点只遍历一次。最深的点最先,根结点最后,加入结果数组res的头部(index = 0处)。
保证正确的原因是,每条路径都DFS过,保证每条路径都是按顺序来的。所以就算有123都指向4,但是每条路上都有1-4,2-4,3-4的方向,这样就能保证4一定会出现在123(可能乱序分布)的后面。比如这个图最后的输出是032514。就是dfs每条路径都是它按顺序的子集(中途有些visited会出现同等级乱序,但每条路径顺序不乱)。
有一点感觉:主函数里的for循环是为了所有分散的团块也不被漏掉能被遍历到所做的;dfs里的for循环是为了从某个点出发能保证所有毛细分支都有被dfs到做的。
参考:https://segmentfault.com/a/1190000004913624
 
 
1.BFS
/**
 * Definition for Directed graph.
 * class DirectedGraphNode {
 *     int label;
 *     ArrayList<DirectedGraphNode> neighbors;
 *     DirectedGraphNode(int x) { label = x; neighbors = new ArrayList<DirectedGraphNode>(); }
 * };
 */

public class Solution {
    /*
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
    public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
        // write your code here
        ArrayList<DirectedGraphNode> result = new ArrayList<DirectedGraphNode>();
        if (graph == null || graph.size() == 0) {
            return result;
        }
        Queue<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>();
        Map<DirectedGraphNode, Integer> map = mapIndegree(graph);
        
        List<DirectedGraphNode> starts = new ArrayList<DirectedGraphNode>();
        for (DirectedGraphNode node : graph) {
            if (map.get(node) == 0) {
                starts.add(node);
            }
        }
        
        // 不是说从每个入度为0的点开始进去试试!而是一开始就把这些点全加进queue!!
        // 如果你只加其中一个点,那之后其他的入度0点永远不会被BFS到加进去的!
        for (DirectedGraphNode start : starts) {
            queue.offer(start);
        }
            
        while (!queue.isEmpty()) {
            DirectedGraphNode crt = queue.poll();
            result.add(crt);
            for (DirectedGraphNode neighbor : crt.neighbors) {
                map.put (neighbor, map.get(neighbor) - 1);
                if (map.get(neighbor) == 0) {
                    queue.offer(neighbor);
                }
            }
        }
        if (result.size() == graph.size()) {
            return result;
        }
        result.clear();
        return result;
    }
    
    private Map<DirectedGraphNode, Integer> mapIndegree(ArrayList<DirectedGraphNode> graph) {
        
        Map<DirectedGraphNode, Integer> map = new HashMap<>();
        for (DirectedGraphNode node : graph) {
            map.put(node, 0);
        }
        for (DirectedGraphNode node : graph) {
            for (DirectedGraphNode neighbor: node.neighbors) {
                map.put(neighbor, map.get(neighbor) + 1);
            }
        }
        return map;
    }
}

 

2.DFS(短但难想)
public class Solution {
    public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
        ArrayList<DirectedGraphNode> res = new ArrayList();
        Set<DirectedGraphNode> visited = new HashSet();
        for (DirectedGraphNode node: graph) {
            if (!visited.contains(node)) {
                dfs(node, visited, res);
            }
        }
        return res;
    }
    public void dfs(DirectedGraphNode node, Set<DirectedGraphNode> visited, List<DirectedGraphNode> res) {
        visited.add(node);
        for (DirectedGraphNode n: node.neighbors) {
            if (!visited.contains(n)) dfs(n, visited, res);
        }
        res.add(0, node);
    }
}

 

posted @ 2017-10-25 13:10  jasminemzy  阅读(144)  评论(0编辑  收藏  举报