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);
    }
}

 

转载于:https://www.cnblogs.com/jasminemzy/p/7728311.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值