Skip to content

Latest commit

 

History

History
executable file
·
214 lines (200 loc) · 6.66 KB

207. Course Schedule.md

File metadata and controls

executable file
·
214 lines (200 loc) · 6.66 KB

207. Course Schedule

Question

There are a total of n courses you have to take, labeled from 0 to n-1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example 1:

Input: 2, [[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: 2, [[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.

Thinking:

  • Method:拓扑图, bfs
    • 先构造邻接表,将所有入度为0的结点都加入队列中。
    • 按序取出所结点,最后无法被取出的说明造成了环路,永远都会有入度并且无法消除。
class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        Map<Integer, List<Integer>> adj = new HashMap<>();
        int[] indegree = new int[numCourses];
        int count = 0;
        for(int i = 0; i < prerequisites.length; i++){
            int first = prerequisites[i][0];
            int second = prerequisites[i][1];
            if(!adj.containsKey(first))
                adj.put(first, new ArrayList<Integer>());
            adj.get(first).add(second);
            indegree[second] ++;
        }
        LinkedList<Integer> q = new LinkedList<>();
        for(int i = 0; i < numCourses; i++)
            if(indegree[i] == 0)
                q.add(i);
        while(!q.isEmpty()){
            Integer pre = q.poll();
            System.out.println(pre);
            count ++;
            List<Integer> temp = null;
            if(adj.containsKey(pre)){
                temp = adj.get(pre);
                for(Integer num : temp){
                    indegree[num] --;
                    if(indegree[num] == 0)
                        q.add(num);
                }
            }
        }
        return count == numCourses;
    }
}

二刷

  1. Method 1: We can use Khan method to solve this question, which is another version of bfs.
class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        int[] indegree = new int[numCourses];
        Map<Integer, List<Integer>> adj = new HashMap<>();
        for(int[] pre : prerequisites){
            List<Integer> temp = adj.containsKey(pre[0]) ? adj.get(pre[0]) : new ArrayList<Integer>();
            temp.add(pre[1]);
            adj.put(pre[0], temp);
            indegree[pre[1]]++;
        }
        LinkedList<Integer> queue = new LinkedList<>();
        for(int i = 0; i < numCourses; i++){
            if(indegree[i] == 0)  queue.add(i);
        }
        int count = 0;
        while(!queue.isEmpty()){
            int pre = queue.poll();
            count++;
            if(adj.containsKey(pre)){
                List<Integer> list = adj.get(pre);
                for(Integer v : list){
                    indegree[v]--;
                    if(indegree[v] == 0)
                        queue.add(v);
                }
            }
        }
        return count == numCourses;
    }
}
  1. Method 2: Use dfs to solve this problem.
class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        int[] indegree = new int[numCourses];
        Map<Integer, List<Integer>> adj = new HashMap<>();
        boolean[] visited = new boolean[numCourses];
        for(int[] pre : prerequisites){
            indegree[pre[1]]++;
            List<Integer> temp = adj.containsKey(pre[0]) ? adj.get(pre[0]): new ArrayList<>();
            temp.add(pre[1]);
            adj.put(pre[0], temp);
        }
        boolean containsZero = false;
        for(int i = 0; i < numCourses; i++){
            if(indegree[i] == 0 && !visited[i]){
                containsZero = true;
                dfs(i, indegree, visited, adj);
            }
        }
        if(!containsZero) return false;
        for(boolean visit : visited){
            if(!visit) return false;
        }
        return true;
    }
    private void dfs(int cur, int[] indegree, boolean[] visited, Map<Integer, List<Integer>> adj){
        visited[cur] = true;
        if(adj.containsKey(cur)){
            for(Integer next : adj.get(cur)){
                indegree[next]--;
                if(indegree[next] == 0 && !visited[next]){
                    dfs(next, indegree, visited, adj);
                }
            }
        }
    }
}

Third Time

  • Method 1: Topological sort + bfs
     class Solution {
     	public boolean canFinish(int numCourses, int[][] prerequisites) {
     		Map<Integer, List<Integer>> map = new HashMap<>();
     		int[] indegree = new int[numCourses];
     		Set<Integer> remain = new HashSet<>();
     		for(int i = 0; i < numCourses; i++) remain.add(i);
     		for(int[] req : prerequisites){
     			indegree[req[1]]++;
     			List<Integer> next = map.containsKey(req[0]) ? map.get(req[0]): new ArrayList<Integer>();
     			next.add(req[1]);
     			map.put(req[0], next);
     		}
     		Queue<Integer> queue = new LinkedList<>();
     		for(int i = 0; i < numCourses; i++){
     			if(indegree[i] == 0)
     				queue.offer(i);
     		}
     		while(!queue.isEmpty()){
     			int course = queue.poll();
     			remain.remove(course);
     			List<Integer> courses = map.get(course);
     			if(courses == null) continue;
     			for(Integer c : courses){
     				if(--indegree[c] == 0)
     					queue.offer(c);
     			}
     		}
     		return remain.isEmpty();
     	}
     }

Amazon session

  • Method 1: Topological sort
     class Solution {
     	public boolean canFinish(int numCourses, int[][] prerequisites) {
     		Map<Integer, Set<Integer>> map = new HashMap<>();   //key: current course, value: courses that cur is pre 
     		int[] indegree = new int[numCourses];   // indegree of course
     		for(int[] requests : prerequisites){
     			indegree[requests[0]]++;
     			Set<Integer> req = map.getOrDefault(requests[1], new HashSet<>());
     			req.add(requests[0]);
     			map.put(requests[1], req);
     		}
     		Queue<Integer> q = new LinkedList<>();
     		int finished = 0;
     		for(int i = 0; i < numCourses; i++){
     			if(indegree[i] == 0){
     				q.offer(i);
     			}
     		}
     		while(!q.isEmpty()){
     			int c = q.poll();
     			finished++;
     			if(!map.containsKey(c)) continue;   // current course is not any pre-request for any course.
     			for(int course : map.get(c)){
     				if(--indegree[course] == 0)
     					q.offer(course);
     			}
     		}
     		return finished == numCourses;
     	}
     }

Reference

  1. 【图论】有向无环图的拓扑排序