图算法(三)-拓扑排序 207, 210, 269

 
207. Course Schedule
Medium

There are a total of numCourses courses you have to take, labeled from 0 to numCourses - 1. You are given an array prerequisites where prerequisites[i] = [ai, bi] indicates that you must take course bi first if you want to take course ai.

  • For example, the pair [0, 1], indicates that to take course 0 you have to first take course 1.

Return true if you can finish all courses. Otherwise, return false.

Example 1:

Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take. 
To take course 1 you should have finished course 0. So it is possible.

Example 2:

Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take. 
To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible. 

Constraints:

  • 1 <= numCourses <= 105
  • 0 <= prerequisites.length <= 5000
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • All the pairs prerequisites[i] are unique.

bfs 

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        //1.build graph
        //2.build dgree
        Map<Integer,List<Integer>> map = new HashMap();
        int[] degree = new int[numCourses];
        for(int[] pair:prerequisites){
            List<Integer> list = map.getOrDefault(pair[1],new ArrayList());
            list.add(pair[0]);
            map.put(pair[1],list);
            degree[pair[0]]++;
        }
        //3.find the entry(degree==0)
        Queue<Integer> queue = new LinkedList();
        for(int i=0;i<numCourses;i++) if(degree[i]==0) queue.offer(i);
        //4.toplogical
        int count=0;
        while(!queue.isEmpty()){
            int curr = queue.poll();
            count++;
            for(int other:map.getOrDefault(curr,Arrays.asList())){
                if(--degree[other] == 0) queue.offer(other);//入度为0的时候进queue
            }
        }
        return count==numCourses;
    }
}

dfs

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        //1.build graph
        Map<Integer,List<Integer>> map = new HashMap();
        for(int[] pair:prerequisites){
            List<Integer> list = map.getOrDefault(pair[1],new ArrayList());
            list.add(pair[0]);
            map.put(pair[1],list);
        }
        int[] visited = new int[numCourses];
        for(int i=0;i<numCourses;i++){
            if(visited[i]==0) if(!dfs(map,visited,i)) return false;
        }
        return true;
    }
    private boolean dfs(Map<Integer,List<Integer>> map ,int[] visited,int curr){
        visited[curr]=1;
        for(int other:map.getOrDefault(curr,Arrays.asList())){
            if(visited[other]==0) {
                if(!dfs(map,visited,other)) return false;
            }
            else if(visited[other]==1) return false;
        }
        visited[curr]=2;
        return true;
    }
}
210. Course Schedule II
Medium

There are a total of numCourses courses you have to take, labeled from 0 to numCourses - 1. You are given an array prerequisites where prerequisites[i] = [ai, bi] indicates that you must take course bi first if you want to take course ai.

  • For example, the pair [0, 1], indicates that to take course 0 you have to first take course 1.

Return the ordering of courses you should take to finish all courses. If there are many valid answers, return any of them. If it is impossible to finish all courses, return an empty array.

Example 1:

Input: numCourses = 2, prerequisites = [[1,0]]
Output: [0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is [0,1].

Example 2:

Input: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
Output: [0,2,1,3]
Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0.
So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3].

Example 3:

Input: numCourses = 1, prerequisites = []
Output: [0]

Constraints:

  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= numCourses * (numCourses - 1)
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • ai != bi
  • All the pairs [ai, bi] are distinct.
class Solution {
    public int[] findOrder(int numCourses, int[][] pre) {
        int[] result = new int[numCourses];
        //1.build graph and degree
        Map<Integer,List<Integer>> map = new HashMap(); // graph
        int[] degrees = new int[numCourses];//degree
        for(int[] edge:pre){
            int end = edge[0],start=edge[1];
            degrees[end]++;
            List<Integer> list = map.getOrDefault(start,new ArrayList());
            if(list.isEmpty()) map.put(start,list);
            list.add(end);
        }
        //2.find the entry course(degree==0)
        Queue<Integer> queue = new LinkedList();
        for(int i=0;i<numCourses;i++) if(degrees[i]==0) queue.offer(i);
        int ind=0;
        //3.bfs traversal
        while(!queue.isEmpty()){
            int curr = queue.poll();
            result[ind++]=curr;
            for(int other:map.getOrDefault(curr,Arrays.asList())){
                if(--degrees[other]==0) queue.offer(other);
            }
        }
        return ind==numCourses ?  result : new int[]{};
    }
}

dfs

class Solution {
    public int[] findOrder(int numCourses, int[][] pre) {
        int[] result = new int[numCourses];
        //1.build graph and degree
        Map<Integer,List<Integer>> map = new HashMap(); // graph
        int[] degrees = new int[numCourses];//degree
        for(int[] edge:pre){
            int end = edge[0],start=edge[1];
            degrees[end]++;
            List<Integer> list = map.getOrDefault(start,new ArrayList());
            if(list.isEmpty()) map.put(start,list);
            list.add(end);
        }
        int[] visited = new int[numCourses];
        ind=numCourses-1;
        for(int i=0;i<numCourses;i++) dfs(map,i,result,visited);
        return isValid ? result : new int[]{};
    }
    private int ind=0;
    private boolean isValid=true;
    private void dfs(Map<Integer,List<Integer>> map,int curr,int[] result,int[] visited){
        if(visited[curr]==1){
            isValid=false;
            return;
        }
        if(visited[curr]==2) return; 
        visited[curr]=1;
        for(int other:map.getOrDefault(curr,Arrays.asList())){
            dfs(map,other,result,visited);
        }
        visited[curr]=2;
        result[ind--]=curr;
    }
}
269 · Alien Dictionary
Algorithms
Description

There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.

  1. You may assume all letters are in lowercase.
  2. The dictionary is invalid, if a is prefix of b and b is appear before a.
  3. If the order is invalid, return an empty string.
  4. There may be multiple valid order of letters, return the smallest in normal lexicographical order
Example

Example 1:

Input:["wrt","wrf","er","ett","rftt"]
Output:"wertf"
Explanation:
from "wrt"and"wrf" ,we can get 't'<'f'
from "wrt"and"er" ,we can get 'w'<'e'
from "er"and"ett" ,we can get 'r'<'t'
from "ett"and"rftt" ,we can get 'e'<'r'
So return "wertf"

Example 2:

Input:["z","x"]
Output:"zx"
Explanation:
from "z" and "x",we can get 'z' < 'x'
So return "zx"
public class Solution {
    public String alienOrder(String[] words) {
        //1.build graph
        Map<Character,List<Character>> map = new HashMap();
        Map<Character,Integer> degree = new HashMap();
        build(map,words,degree);
        //2.find the entry
        PriorityQueue<Character> queue = new PriorityQueue<>((x,y)->x-y);
        for(char c:degree.keySet()) if(degree.get(c)==0) queue.offer(c);
        //3.bfs
        StringBuffer sb = new StringBuffer("");
        while(!queue.isEmpty()){
            char curr = queue.poll();
            sb.append(curr);
            for(char other:map.getOrDefault(curr,Arrays.asList())){
                degree.put(other,degree.get(other)-1);
                if(degree.get(other)==0) queue.offer(other);
            }
        }
return sb.length() == degree.size() ? sb.toString() : "";
    }
    private boolean valid = true;
    private void build(Map<Character,List<Character>> map,String[] words,Map<Character,Integer> degree){
        for(String s:words){
            for(char c:s.toCharArray()){
                map.put(c,new ArrayList());
                degree.put(c,0);
            }
        }
        for(int i=1;i<words.length;i++){
            String a = words[i-1];
            String b = words[i];
            if(a.length()>b.length() && a.startsWith(b)) { //坑点 举例:["abc", "ab"]
                valid=false;
                return;
            }
            for(int j=0;j< Math.min(a.length(),b.length());j++){
                char ca = a.charAt(j);char cb = b.charAt(j);
                if(ca!=cb){
                    map.get(ca).add(cb);
                    degree.put(cb,degree.get(cb)+1);
                    break;
                }
            }
        }
    }
}

 

posted @ 2021-12-20 02:34  xiaoyongyong  阅读(55)  评论(0)    收藏  举报