资讯专栏INFORMATION COLUMN

[Leetcode] Course Schedule 课程计划

Amio / 2739人阅读

Course Schedule I
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?

For example:

2, [[1,0]] There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.

2, [[1,0],[0,1]] 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.

Note: The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.

拓扑排序 复杂度

时间 O(N) 空间 O(N)

思路

先修课问题本质上是一个有向图,如果这个图无环,我们可以根据拓扑排序遍历到所有节点,如果有环则拓扑排序无法完成,遍历到的节点将少于总节点数,因为有的节点是孤岛。这题我们先根据边的关系,建一个图,并计算每个节点的入度,这里用的是数组来建图。然后从入度为0的节点,也就是入口开始广度优先搜索,按照拓扑排序的顺序遍历,最后看遍历过的节点数和总节点数的关系就行了。拓扑排序的使用方法参见外文字典。

代码
public class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        ArrayList[] graph = new ArrayList[numCourses];
        int[] indegree = new int[numCourses];
        // 先初始化图,每个赋一个空列表
        for(int i = 0; i < numCourses; i++){
            graph[i] = new ArrayList();
        }
        // 根据边建立图,并计算入度
        for(int i = 0; i < prerequisites.length; i++){
            graph[prerequisites[i][1]].add(prerequisites[i][0]);
            indegree[prerequisites[i][0]]++;
        }
        // 找到有向图的入口
        Queue queue = new LinkedList();
        for(int i = 0; i < indegree.length; i++){
            if(indegree[i] == 0){
                queue.add(i);
            }
        }
        // 按照拓扑排序的顺序,进行广度优先搜索
        int cnt = 0;
        while(!queue.isEmpty()){
            Integer curr = queue.poll();
            cnt++;
            ArrayList nexts = graph[curr];
            for(int i = 0; i < nexts.size(); i++){
                int next = nexts.get(i);
                indegree[next]--;
                if(indegree[next] == 0){
                    queue.offer(next); 
                }
            }
        }
        return cnt == numCourses;
    }
}

2018/10

func canFinish(numCourses int, prerequisites [][]int) bool {
    graph := make(map[int][]int)
    indegree := make([]int, numCourses)
    // build the graph, count the indegree for each course
    for _, prerequisite := range prerequisites {
        course1 := prerequisite[0]
        course2 := prerequisite[1]
        if graph[course2] != nil {
            graph[course2] = append(graph[course2], course1)
        } else {
            graph[course2] = []int{course1}
        }
        indegree[course1]++
    }
    // find out those with 0 indegree as roots of the graph
    var queue []int
    for i, degree := range indegree {
        if degree == 0 {
            queue = append(queue, i)
        }
    }
    // traverse the graph from each root, decrement the indegree for each leaf
    count := 0
    for len(queue) > 0 {
        curr := queue[0]
        queue = queue[1:]
        count++
        for _, course := range graph[curr] {
            indegree[course]--
            // once a node"s indegree is 0, it becomes a root too
            if indegree[course] == 0 {
                queue = append(queue, course)
            }
        }
    }
    // if all nodes have been the root before, we traversed the entire graph
    return count == numCourses
}
Course Schedule II
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, return the ordering of courses you should take to finish all courses.

There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.

For example:

2, [[1,0]] 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]

4, [[1,0],[2,0],[3,1],[3,2]] 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].

拓扑排序 复杂度

时间 O(N) 空间 O(N)

思路

和I不同的是,这题要返回路径。其实也没有什么不同的,不过是多加一个数组,记录广度优先搜索的遍历顺序就行了。

注意

当没有先修课的时候,随便返回一个顺序就行了,所以初始化的时候就初始化为升序序列,方便后面直接返回。

代码
public class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        int[] res = new int[numCourses];
        ArrayList[] graph = new ArrayList[numCourses];
        int[] indegree = new int[numCourses];
        for(int i = 0; i < prerequisites.length; i++){
            if(graph[prerequisites[i][1]] == null){
                graph[prerequisites[i][1]] = new ArrayList();
            }
            graph[prerequisites[i][1]].add(prerequisites[i][0]);
            indegree[prerequisites[i][0]]++;
        }
        Queue queue = new LinkedList();
        for(int i = 0; i < indegree.length; i++){
            if(indegree[i] == 0){
                queue.add(i);
            }
        }
        // 用idx记录输出数组的下标
        int idx = 0;
        while(!queue.isEmpty()){
            Integer curr = queue.poll();
            res[idx++] = curr;
            if(graph[curr] == null) continue;
            for(Integer next : graph[curr]){
                if(--indegree[next] == 0){
                    queue.offer(next); 
                }
            }
        }
        // 如果有环则返回空数组
        return idx != numCourses ? new int[0] : res;
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64634.html

相关文章

  • 210. Course Schedule II

    摘要:建立入度组成,把原来输入的无规律,转换成另一种表示图的方法。找到为零的点,放到里,也就是我们图的入口。对于它的也就是指向的。如果这些的入度也变成,也就变成了新的入口,加入到里,重复返回结果。这里题目有可能没有预修课,可以直接上任意课程。 Some courses may have prerequisites, for example to take course 0 you have ...

    lbool 评论0 收藏0
  • [LeetCode] 210. Course Schedule II

    Problem 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...

    zhkai 评论0 收藏0
  • [LeetCode/LintCode] Course Schedule II

    Problem 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 a...

    Lavender 评论0 收藏0
  • [LeetCode] 207. Course Schedule

    Problem 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 ...

    ephererid 评论0 收藏0
  • 207. Course Schedule

    摘要:题目解答这是一个有向图问题,所以先建图,然后再扫。同时记录一共存了多少课程在里,这些课都是可以上的课。如果当两个点在同时访问的时候,那么构成死循环,返回。扫完所有的点都没问题,才返回。这里总是忘记,当中时,才否则继续循环 题目:There are a total of n courses you have to take, labeled from 0 to n - 1. Some c...

    Nino 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<