(番外)使用DFS和BFS实现拓扑排序

时间:2023-02-02 14:38:59

1.BFS实现

public class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        int[] incLinkCounts = new int[numCourses];
        List<List<Integer>> adjs = new ArrayList<>(numCourses);
        initialiseGraph(incLinkCounts, adjs, prerequisites);
    //return solveByBFS(incLinkCounts, adjs);
        return solveByBFS(incLinkCounts,adjs);
    }
    
    private void initialiseGraph(int[] incLinkCounts, List<List<Integer>> adjs, int[][] prerequisites){
        int n = incLinkCounts.length;
        while (n-- > 0) adjs.add(new ArrayList<>());
        for (int[] edge : prerequisites) {
            incLinkCounts[edge[0]]++;
            adjs.get(edge[1]).add(edge[0]);
        }
   }
   
   private int[] solveByBFS(int[] incLinkCounts, List<List<Integer>> adjs){
       int[] order = new int[incLinkCounts.length];
       Queue<Integer> toVisit = new ArrayDeque<>();
       for (int i = 0; i < incLinkCounts.length; i++) {
           if (incLinkCounts[i] == 0) toVisit.offer(i);
            }
       int visited = 0;
       while (!toVisit.isEmpty()) {
           int from = toVisit.poll();
           order[visited++] = from;
           for (int to : adjs.get(from)) {
               incLinkCounts[to]--;
               if (incLinkCounts[to] == 0) toVisit.offer(to);
           }
       }
    return visited == incLinkCounts.length ? order : new int[0]; 
   }
}

2.DFS实现

public class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        int[] incLinkCounts = new int[numCourses];
        List<List<Integer>> adjs = new ArrayList<>(numCourses);
        initialiseGraph(incLinkCounts, adjs, prerequisites);
    //return solveByBFS(incLinkCounts, adjs);
        return  solveByDFS(adjs);
    }
    
    private void initialiseGraph(int[] incLinkCounts, List<List<Integer>> adjs, int[][] prerequisites){
        int n = incLinkCounts.length;
        while (n-- > 0) adjs.add(new ArrayList<>());
        for (int[] edge : prerequisites) {
            incLinkCounts[edge[0]]++;
            adjs.get(edge[1]).add(edge[0]);
        }
   }
   
   private int[] solveByBFS(int[] incLinkCounts, List<List<Integer>> adjs){
       int[] order = new int[incLinkCounts.length];
       Queue<Integer> toVisit = new ArrayDeque<>();
       for (int i = 0; i < incLinkCounts.length; i++) {
           if (incLinkCounts[i] == 0) toVisit.offer(i);
            }
       int visited = 0;
       while (!toVisit.isEmpty()) {
           int from = toVisit.poll();
           order[visited++] = from;
           for (int to : adjs.get(from)) {
               incLinkCounts[to]--;
               if (incLinkCounts[to] == 0) toVisit.offer(to);
           }
       }
    return visited == incLinkCounts.length ? order : new int[0]; 
   }
   
   private int[] solveByDFS(List<List<Integer>> adjs) {
       BitSet hasCycle = new BitSet(1);
       BitSet visited = new BitSet(adjs.size());
       BitSet onStack = new BitSet(adjs.size());
       Deque<Integer> order = new ArrayDeque<>();
       for (int i = adjs.size() - 1; i >= 0; i--) {
           if (visited.get(i) == false && hasOrder(i, adjs, visited, onStack, order) == false) return new int[0];
       }
       int[] orderArray = new int[adjs.size()];
       for (int i = 0; !order.isEmpty(); i++) orderArray[i] = order.pop();
       return orderArray;
   }

private boolean hasOrder(int from, List<List<Integer>> adjs, BitSet visited, BitSet onStack, Deque<Integer> order) {
    visited.set(from);
    onStack.set(from);
    for (int to : adjs.get(from)) {
        if (visited.get(to) == false) {
            if (hasOrder(to, adjs, visited, onStack, order) == false) return false;
        } else if (onStack.get(to) == true) {
            return false;
        }
    }
    onStack.clear(from);
    order.push(from);
    return true;
   }
}