算法题目---BFS解决拓扑排序

(一).概念

关于"拓扑排序",主要看图片中的内容来理解。

(二).具体题目

1.课程表

207. 课程表 - 力扣(LeetCode)

解法:拓扑排序

java 复制代码
class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        //1.准备工作
        int[] inArr=new int[numCourses];   //统计入度
        HashMap<Integer, List<Integer>> hashMap=new HashMap<>();  //使用邻接表存图
        //2.建图
        for (int i = 0; i < prerequisites.length; i++) {
            int a=prerequisites[i][0];
            int b=prerequisites[i][1];
            if (!hashMap.containsKey(b)){
                hashMap.put(b,new ArrayList<>());
            }
            hashMap.get(b).add(a);
            inArr[a]++;
        }

        //3.拓扑排序
        Queue<Integer> queue=new ArrayDeque<>();
        //(1).将所有入度为0的点放入到队列中
        for (int i = 0; i < numCourses; i++) {
            if (inArr[i]==0){
                queue.add(i);
            }
        }
        //(2).进行bfs
        while (!queue.isEmpty()){
            Integer poll = queue.poll();
            List<Integer> list = hashMap.getOrDefault(poll,new ArrayList<>());
            for(int x:list){  //减少入度
                inArr[x]--;
                if (inArr[x]==0){  //将入度为0的点加入到队列中
                    queue.add(x);
                }
            }
        }
        //4.判断是否有环
        for (int i = 0; i < numCourses; i++) {
            if (inArr[i]!=0){
                return false;
            }
        }
        return true;
    }
}

2.课程表Ⅱ

210. 课程表 II - 力扣(LeetCode)

解法:拓扑排序

java 复制代码
class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        //1.准备工作
        int[] ret=new int[numCourses];
        int pos=0;  //标记结果数组的位置
        int[] inArr=new int[numCourses];  //统计每个节点的入度
        HashMap<Integer,List<Integer>> hashMap=new HashMap<>(); //使用邻接表来存储图
        //2.建图
        for (int i = 0; i < prerequisites.length; i++) {
            int a=prerequisites[i][0];
            int b=prerequisites[i][1];
            if (!hashMap.containsKey(b)){
                hashMap.put(b,new ArrayList<>());
            }
            hashMap.get(b).add(a);
            inArr[a]++;
        }
        //3.拓扑排序
        Queue<Integer> queue=new ArrayDeque<>();
        for (int i = 0; i < inArr.length; i++) {
            if (inArr[i]==0){
                queue.add(i);
            }
        }
        //4.bfs
        while (!queue.isEmpty()){
            Integer poll = queue.poll();//相当于从"图谱排序"中找到了一个点
            ret[pos++]=poll;  //将这个点添加到数组中,因为,但是是从队列中取出来的,那么说明这个点的入度一定为0了
            List<Integer> list = hashMap.getOrDefault(poll,new ArrayList<>());
            for(int x:list){
                inArr[x]--;
                if (inArr[x]==0){
                    queue.add(x);
                }
            }
        }
        if (pos==numCourses){  //如果最后的pos和numCourses相等,那么说明所有的值都存在ret中了
            return ret;
        }else{
            return new int[0];
        }
    }
}

3.火星词典

LCR 114. 火星词典 - 力扣(LeetCode)

解法:拓扑排序

java 复制代码
class Solution {
    HashMap<Character, HashSet<Character>> hashMap=new HashMap<Character, HashSet<Character>>(); //建图使用的哈希表
    HashMap<Character,Integer> in=new HashMap<>();  //统计入度信息
    boolean check;
    public String alienOrder(String[] words) {
        for(String str:words){
            for (int i = 0; i < str.length(); i++) {
                in.put(str.charAt(i),0);
            }
        }

        for (int i = 0; i < words.length; i++) {
            for (int j = i+1; j < words.length; j++) {
                add(words[i],words[j]);
                if (check==true){
                    return "";  //特殊情况
                }
            }
        }
        Queue<Character> queue=new ArrayDeque<>();
        for (char ch:in.keySet()){
            if (in.get(ch)==0){
                queue.add(ch);
            }
        }
        StringBuilder stringBuilder=new StringBuilder();
        while (!queue.isEmpty()){
            Character poll = queue.poll();
            stringBuilder.append(poll);
            if (!hashMap.containsKey(poll)){
                continue;  //如果不存在哈希表中,说明没有顺序关系,此时直接跳过这次循环即可
            }
            for(char ch:hashMap.get(poll)){
                in.put(ch,in.get(ch)-1);
                if (in.get(ch)==0){
                    queue.add(ch);
                }
            }
        }

        for(char ch:in.keySet()){
            if (in.get(ch)!=0){
                return "";
            }
        }
        return stringBuilder.toString();
    }

    private void add(String s1, String s2) {
        int len=Math.min(s1.length(),s2.length());
        int i = 0;
        for (; i < len; i++) {
            char c1=s1.charAt(i);
            char c2=s2.charAt(i);
            if (c1!=c2){
                if (!hashMap.containsKey(c1)){
                    hashMap.put(c1,new HashSet<>());
                }
                if (!hashMap.get(c1).contains(c2)){
                    hashMap.get(c1).add(c2);
                    in.put(c2,in.get(c2)+1);
                }
                break;
            }
        }
        if (i==s2.length() && i<s1.length()){
            check=true;
        }
    }
}