210. Course Schedule II

题目:课程表2

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

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

click to show more hints.

Hints:
  1. This problem is equivalent to finding the topological order in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
  2. Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
  3. Topological sort could also be done via BFS.

题意:

总共有标记为0到n-1的n门课程需要你选择。

有些课程可能需要一些先决条件,例如,要想选课程0,你就必须要先选课程1,使用一个键值对[0, 1]表示这样的情况。

给定课程的总数和一些先决条件键值对,返回你能完成所有课程的课程表顺序

可能会有多种正确的课程表顺序,只需要返回其中一种即可。如果不能完成所有的课程,返回一个空数组。

Note:

输入的先决条件键值对是用一个图的边表示的,而不是使用邻接矩阵。阅读更多关于如何表示一个图。

Hints:

1、这个问题等效于找到有向图中是否有循环存在。如果存在一个循环,不存在拓扑排序,因此不可能将所有的可能学习完。

2、通过DFS实现拓扑排序,在Coursera上有一个21分钟左右的很好的视频教程,讲述了拓扑排序的基本概念。

3、拓扑排序也可以通过BFS实现。


思路一:

这题是之前那道 Course Schedule 课程清单的扩展,那道题只让我们判断是否能完成所有课程,即检测有向图中是否有环,而这道题我们得找出要上的课程的顺序,即有向图的拓扑排序,这样一来,难度就增加了,但是由于我们有之前那道的基础,而此题正是基于之前解法的基础上稍加修改,我们从queue中每取出一个数组就将其存在结果中,最终若有向图中有环,则结果中元素的个数不等于总课程数,那我们将结果清空即可。

代码:C++版:28ms

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<int> res;
        vector<vector<int>> graph(numCourses, vector<int>(0));
        vector<int> in(numCourses, 0);
        for (auto &a : prerequisites) { //a.first表示想要修的课程,a.second表示a.first的预备课程
            graph[a.second].push_back(a.first); //转换生成有向图
            ++in[a.first];
        }
        queue<int> q;
        for (int i=0; i<numCourses; ++i) { //将入度为0的节点放入队列中
            if (in[i] == 0) q.push(i);
        }
        while (!q.empty()) {
            int t = q.front();
            res.push_back(t);
            q.pop();
            for (auto &a : graph[t]) {
                --in[a];
                if (in[a] == 0) q.push(a);
            }
        }
        if (res.size() != numCourses) res.clear();
        return res;
    }
};

思路二:

拓扑排序:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

DFS实现,过程与Course Schedule题目的DFS类似,先利用给定的numCourses以及prerequisites来生成图,之后通过维护onpath以及visited数组来记录递归过程中所遍历过得图路径,在递归过程中,将满足题目要求的路径节点放入toposort数组中,作为返回数组输出。

代码:C++版:32ms

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<unordered_set<int>> graph = make_graph(numCourses, prerequisites);
        vector<int> toposort;
        vector<bool> onpath(numCourses, false), visited(numCourses, false);
        for (int i=0; i<numCourses; i++) {
            if (!visited[i] && dfs(graph, i, onpath, visited, toposort))
                return {};
        }
        reverse(toposort.begin(), toposort.end());
        return toposort;
    }
private:
    //初始化图,生成图
    vector<unordered_set<int>> make_graph(int numCourses, vector<pair<int, int>> &prerequisites) {
        vector<unordered_set<int>> graph(numCourses);
        for (auto pre : prerequisites) {
            graph[pre.second].insert(pre.first);
        }
        return graph;
    }
    //递归完成遍历
    bool dfs(vector<unordered_set<int>> &graph, int node, vector<bool> &onpath, vector<bool> &visited, vector<int> &toposort) {
        if (visited[node]) return false;
        onpath[node] = visited[node] = true;
        for (int neigh : graph[node]) 
            if (onpath[neigh] || dfs(graph, neigh, onpath, visited, toposort))
                return true;
        toposort.push_back(node);
        return onpath[node] = false;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值