Leetcode 207 Course Schedule 课程表

这道LeetCode题目要求判断给定课程的先决条件下,是否能完成所有课程。它涉及到有向图的拓扑排序,可以使用DFS或BFS来解决。题目提供了两种解决方案的代码链接。

原题地址

https://leetcode.com/problems/course-schedule/

题目描述

There are a total of n courses you have to take, labeled from 0 to n - 1.
你需要上n个课程,标记为0~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]
有些课程有前导课,比如你要上课程0必须先上课程1,我们用一个整数对[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个课程,你需要先上课程0再上课程1,因此是可能的。

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.
共有2个课程,你需要先上课程0再上课程1,而且上课程1之前你必须先上课程0,因此这是不可能的。

Note:
注意:

The input prerequisites is a graph represented by a list of edges, not adjacency matrices.
输入的先序关系代表着一个图的边,不是邻接矩阵。

Hints:
提示:

  1. This problem is equivalent to finding if a cycle exists 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.
    拓扑排序可以用深度优先搜索来实现。
  3. Topological sort could also be done via BFS.
    拓扑排序可以用广度优先搜索来实现。

Tags Depth-first Search Breadth-first Search Graph Topological Sort

解题思路

使用广度优先搜索来实现拓扑排序的解题思路类似于这个题 hihocoder 47 拓扑排序 · 一,所以此处就不做描述了。代码和测试数据后面给出。

使用深度优先搜索的解题思路跟广度优先搜索类似,差别在于我们不是根据入度来确定搜索次序,而是根据出度来确定搜索次序,即维护出度为0的结点的集合,依次移除这些结点,并更新未其相应边的出度,直至所有结点的出度不再变化,如果最终所有结点的出度都为0则不存在环

在判断有向图是否有环的问题上,bfs和dfs的区别仅在是按照入度还是出度来考虑问题上。

另外,关于课程的具体顺序,详见Leetcode 210 Course Schedule II

代码

dfs

class Solution {
public:
    /**
     * 能否完成所有的课程
     * dfs拓扑排序,看有向图是否存在环
     * @param numCourses 课程数量
     * @param prerequisites 课程先序关系
     * @return 能完成返回true,否则false
     */
    bool canFinish(int numCourses, vector<pair<int, int> >& prerequisites) {
        vector<int> heads(numCourses, -1), degree(numCourses, 0), points, args;
        pair<int, int> p;
        int from, to, count = 0, len = prerequisites.size();

        /* 构造有向图,邻接表 */
        for (int i = 0; i < len; ++i) {
            p = prerequisites[i];
            from = p.second;
            to = p.first;
            ++degree[from];
            args.push_back(heads[to]);
            points.push_back(from);
            heads[to] = count++;
        }

        /* dfs拓扑排序,依次移除出度为0的点 */
        queue<int> q;
        for (int i = 0; i < numCourses; ++i) 
            if (degree[i] == 0) q.push(i);
        while (!q.empty()) {
            to = q.front();
            q.pop();
            from = heads[to];
            while (from != -1) {
                if(--degree[points[from]] == 0) q.push(points[from]);
                from = args[from];
            }
        }

        /* 判定是否所有的点入度都为0,若是则不存在环,否则存在环 */
        for (int i = 0; i < numCourses; ++i)
            if (degree[i] > 0) 
                 return false;

        return true;
    }
};

完整代码 https://github.com/Orange1991/leetcode/blob/master/207/cpp/dfs.cpp

bfs

class Solution {
public:
    /**
     * 能否完成所有的课程
     * bfs拓扑排序,看有向图是否存在环
     * @param numCourses 课程数量
     * @param prerequisites 课程先序关系
     * @return 能完成返回true,否则false
     */
    bool canFinish(int numCourses, vector<pair<int, int> >& prerequisites) {
        vector<int> heads(numCourses, -1), degree(numCourses, 0), points, args;
        pair<int, int> p;
        int from, to, count = 0, len = prerequisites.size();

        /* 构造有向图,邻接表 */
        for (int i = 0; i < len; ++i) {
            p = prerequisites[i];
            from = p.second;
            to = p.first;
            ++degree[to];
            args.push_back(heads[from]);
            points.push_back(to);
            heads[from] = count++;
        }

        /* bfs拓扑排序,依次移除入度为0的点 */
        queue<int> q;
        for (int i = 0; i < numCourses; ++i) 
            if (degree[i] == 0) q.push(i);
        while (!q.empty()) {
            from = q.front();
            q.pop();
            to = heads[from];
            while (to != -1) {
                if(--degree[points[to]] == 0) q.push(points[to]);
                to = args[to];
            }
        }

        /* 判定是否所有的点入度都为0,若是则不存在环,否则存在环 */
        for (int i = 0; i < numCourses; ++i)
            if (degree[i] > 0)
                 return false;

        return true;
    }
};

完整代码 https://github.com/Orange1991/leetcode/blob/master/207/cpp/bfs.cpp

测试数据

(1) : 2, [[0,1]] : You can finish all the classes.
(2) : 2, [[0,1],[1,0]] : You can not finish all the classes.
(3) : 6, [[1,0],[2,0],[2,1],[3,2],[4,1],[5,3],[5,0],[5,3],[5,4]] : You can finish all the classes.
(4) : 800, [[695,229],[199,149],[443,397],[258,247],[781,667],[350,160],[678,629],[467,166],[500,450],[477,107],[483,151],[792,785],[752,368],[659,623],[316,224],[487,268],[743,206],[552,211],[314,20],[720,196],[421,103],[493,288],[762,24],[528,318],[472,32],[684,502],[641,354],[586,480],[629,54],[611,412],[719,680],[733,42],[549,519],[697,316],[791,634],[546,70],[676,587],[460,58],[605,530],[617,579],[484,89],[571,482],[767,200],[555,547],[771,695],[624,542],[708,551],[432,266],[656,468],[724,317],[423,248],[621,593],[781,399],[535,528],[578,12],[770,549],[576,295],[318,247],[400,372],[465,363],[786,482],[441,398],[577,411],[524,30],[741,540],[459,59],[758,96],[550,89],[402,295],[476,336],[645,346],[750,116],[551,207],[343,226],[568,498],[530,228],[525,84],[507,128],[526,210],[535,381],[635,330],[654,535],[710,275],[397,213],[412,44],[131,70],[508,49],[679,223],[519,11],[626,286],[242,160],[778,199],[606,281],[226,16],[340,46],[578,127],[212,208],[674,343],[778,108],[749,451],[735,105],[544,131],[600,229],[691,314],[608,74],[613,491],[754,500],[722,449],[486,11],[786,70],[212,23],[717,11],[692,410],[503,157],[783,177],[220,215],[419,363],[182,17],[321,54],[711,78],[312,106],[560,101],[501,178],[583,403],[577,9],[595,227],[601,386],[792,619],[550,167],[589,431],[793,243],[395,76],[197,3],[357,6],[763,7],[599,48],[178,92],[325,307],[620,10],[334,117],[556,296],[454,394],[485,236],[140,80],[404,301],[651,58],[504,455],[101,93],[712,42],[559,421],[594,230],[505,98],[719,654],[672,283],[109,73],[556,183],[617,94],[133,100],[771,515],[613,587],[285,50],[579,432],[282,244],[669,527],[783,494],[628,560],[716,661],[177,127],[430,166],[383,159],[746,19],[653,284],[495,243],[376,57],[560,143],[679,198],[751,355],[339,157],[409,140],[729,389],[518,315],[623,352],[651,133],[761,269],[442,44],[379,245],[313,180],[773,583],[291,221],[271,54],[799,44],[200,102],[568,67],[695,167],[327,36],[431,73],[782,167],[611,129],[630,122],[563,497],[697,93],[596,436],[611,131],[627,256],[658,559],[591,419],[193,156],[302,52],[409,33],[405,249],[384,151],[214,142],[558,164],[565,557],[492,445],[681,271],[797,396],[251,195],[784,266],[607,179],[671,30],[752,179],[787,390],[749,532],[618,220],[659,298],[567,134],[229,208],[298,147],[787,459],[572,359],[794,351],[53,14],[646,422],[234,66],[274,255],[744,626],[730,462],[498,428],[573,288],[688,355],[603,25],[191,16],[793,544],[750,682],[415,156],[460,209],[749,85],[269,186],[441,338],[319,278],[505,18],[672,260],[420,233],[493,134],[493,19],[308,302],[582,282],[755,60],[641,626],[669,69],[772,29],[132,111],[666,120],[605,58],[534,252],[636,491],[777,3],[602,368],[533,287],[401,147],[782,669],[517,161],[686,49],[789,639],[776,379],[376,65],[696,545],[423,81],[448,336],[631,605],[501,387],[413,94],[777,563],[661,332],[756,359],[646,36],[650,283],[656,347],[522,7],[383,382],[438,102],[762,305],[650,15],[249,180],[784,467],[763,122],[163,115],[775,734],[166,132],[634,2],[668,584],[767,274],[595,552],[11,7],[693,407],[789,751],[613,556],[715,402],[751,516],[646,199],[625,52],[572,106],[724,332],[617,409],[573,526],[760,18],[382,202],[207,139],[416,392],[672,358],[233,212],[668,22],[765,452],[294,76],[259,47],[593,271],[510,450],[592,132],[770,558],[296,43],[419,86],[752,347],[615,605],[635,554],[794,635],[613,316],[563,61],[770,715],[771,251],[646,582],[423,79],[576,249],[604,97],[767,348],[736,239],[775,56],[619,601],[790,546],[531,384],[507,84],[564,337],[432,310],[600,543],[747,341],[556,392],[661,113],[449,282],[575,288],[637,7],[635,325],[735,574],[574,387],[705,603],[704,15],[684,588],[495,132],[718,223],[517,206],[272,34],[677,416],[788,167],[649,525],[619,427],[541,277],[489,405],[608,259],[603,264],[435,317],[623,26],[544,511],[72,69],[623,17],[600,544],[551,367],[404,52],[324,272],[706,205],[778,446],[341,155],[581,173],[666,192],[588,529],[554,506],[250,39],[772,116],[569,77],[526,132],[563,221],[655,597],[649,224],[57,4],[679,199],[265,157],[380,335],[558,35],[726,388],[763,567],[437,426],[643,103],[773,181],[726,68],[164,50],[717,427],[681,618],[477,172],[697,423],[525,383],[794,132],[149,70],[704,414],[581,139],[678,204],[107,46],[352,68],[645,178],[758,156],[627,365],[331,144],[547,340],[788,36],[633,259],[588,66],[321,102],[528,322],[212,36],[288,179],[434,189],[749,490],[753,508],[784,341],[550,159],[741,206],[758,688],[766,758],[586,70],[657,654],[701,104],[548,184],[613,162],[620,320],[506,430],[517,65],[571,291],[771,517],[796,756],[735,459],[625,367],[759,345],[582,468],[469,73],[790,352],[493,284],[664,567],[342,207],[669,108],[611,182],[764,485],[214,102],[544,202],[713,447],[793,378],[147,129],[407,198],[608,271],[695,667],[680,277],[222,163],[744,527],[280,116],[430,367],[281,228],[688,488],[733,92],[529,190],[750,718],[793,99],[626,169],[486,329],[620,0],[782,460],[329,16],[753,142],[338,172],[518,361],[688,168],[497,490],[484,365],[365,325],[107,98],[622,407],[527,277],[659,74],[552,538],[493,469],[638,147],[304,3],[573,201],[411,169],[719,309],[287,160],[742,175],[573,299],[562,473],[705,328],[261,98],[580,203],[740,26],[418,296],[764,170],[656,89],[724,536],[730,91],[796,290],[735,270],[512,20],[402,246],[46,30],[426,290],[296,57],[725,222],[324,317],[547,0],[661,136],[636,271],[261,56],[750,668],[647,402],[773,390],[677,62],[249,53],[574,4],[393,304],[701,44],[109,66],[275,109],[679,509],[725,21],[409,311],[368,156],[605,514],[538,42],[690,602],[411,343],[424,240],[78,40],[750,273],[367,230],[167,58],[738,200],[634,341],[409,170],[644,373],[741,296],[702,342],[746,233],[411,67],[526,436],[796,438],[647,312],[717,347],[548,54],[725,50],[549,92],[610,294],[668,350],[578,445],[446,93],[727,246],[526,355],[344,246],[145,54],[355,256],[751,46],[454,271],[587,49],[728,79],[627,49],[522,260],[270,250],[491,113],[337,258],[609,470],[387,147],[656,237],[366,357],[160,98],[761,692],[753,627],[718,5],[335,22],[640,78],[687,317],[315,295],[471,93],[481,147],[724,580],[687,177],[409,41],[355,276],[393,366],[770,85],[697,358],[187,115],[671,318],[716,530],[767,140],[566,543],[318,238],[341,336],[648,204],[496,202],[505,191],[360,32],[408,138],[537,489],[668,102],[400,9],[472,3],[727,469],[713,5],[530,292],[465,381],[551,262],[514,227],[394,315],[551,121],[655,402],[755,83],[153,144],[303,60],[766,578],[668,527],[796,391],[692,571],[617,616],[229,154],[798,690],[706,504],[610,569],[655,624],[408,108],[569,463],[461,151],[507,13],[781,314],[780,469],[506,171],[552,312],[189,164],[336,171],[571,432],[688,224],[160,119],[470,311],[663,114],[665,420],[556,492],[709,358],[202,99],[170,149],[340,154],[666,385],[617,383],[502,132],[220,42],[778,393],[444,68],[526,357],[217,7],[597,76],[586,406],[481,44],[486,240],[513,217],[790,447],[275,245],[396,1],[369,224],[485,159],[680,151],[387,312],[721,70],[733,25],[457,216],[798,297],[329,169],[766,212],[286,160],[703,164],[765,77],[620,142],[510,35],[475,400],[784,8],[768,189],[668,328],[697,2],[389,169],[550,223],[514,268],[579,285],[419,53],[318,96],[335,117],[729,27],[694,281],[349,137],[545,221],[679,100],[382,116],[707,140],[62,48],[664,312],[499,369],[547,350],[509,279],[778,76],[186,17],[741,683],[635,531],[441,391],[493,385],[354,218],[304,128],[651,271],[693,360],[613,112],[798,393],[743,190],[115,62],[725,592],[525,233],[621,517],[327,70],[501,358],[504,346],[787,321],[94,74],[729,339],[50,13],[603,265],[163,29],[781,373],[586,459],[797,741],[624,364],[411,277],[360,161],[690,686],[746,639],[553,325],[631,328],[388,330],[619,210],[573,43],[559,100],[210,152],[378,5],[776,447],[615,181],[365,299],[708,310],[718,690],[268,225],[639,90],[318,5],[196,89],[361,184],[762,690],[772,465],[729,721],[541,331],[567,350],[269,58],[656,78],[579,163],[711,223],[282,268],[760,533],[404,280],[473,384],[94,48],[340,12],[727,364],[264,221],[591,487],[514,466],[305,168],[372,248],[639,499],[560,435],[541,142],[462,83],[594,353],[618,485],[95,33],[602,595],[605,289],[715,207],[448,293],[752,170],[641,203],[532,198],[608,13],[707,114],[744,211],[110,3],[298,228],[622,496],[286,26],[683,178],[706,192],[751,358],[486,461],[561,251],[466,193],[342,62],[221,37],[731,325],[205,132],[518,173],[502,261],[640,49],[541,522],[747,110],[756,591],[124,76],[639,603],[765,482],[388,5],[34,12],[514,344],[495,254],[770,751],[730,597],[708,105],[683,586],[528,288],[386,225],[287,26],[649,262],[753,670],[789,85],[632,439],[570,176],[672,652],[445,399],[400,226],[655,522],[469,249],[557,500],[275,6],[397,296],[725,43],[605,533],[425,220],[637,118],[628,215],[654,431],[697,421],[512,121],[237,36],[151,85],[574,217],[320,233],[492,272],[552,220],[739,81],[712,219],[612,590],[410,66],[548,40],[320,211],[381,95],[633,482],[742,535],[704,131],[682,435],[508,48],[435,337],[534,96],[663,653],[283,205],[715,74],[484,376],[585,366],[635,479],[753,719],[793,548],[396,171],[156,112],[575,380],[717,464],[612,576],[569,319],[736,259],[406,227],[711,709],[793,132],[528,295],[592,48],[731,217],[408,299],[373,137],[786,327],[791,166],[712,285],[772,603],[723,338],[531,121],[572,548],[786,167],[670,401],[724,440],[280,229],[497,453],[265,70],[733,144],[689,434],[504,384],[93,64],[563,397],[550,106],[224,198],[372,177],[249,31],[667,372],[263,78],[783,446],[791,59],[438,64],[630,270],[216,160],[704,261],[674,506],[704,23],[378,4],[784,437],[196,118],[681,314],[698,663],[397,274],[499,440],[737,265],[697,625],[139,84],[440,231],[453,150],[266,55],[377,11],[728,60],[431,202],[268,47],[763,123],[347,339],[470,117],[466,298],[344,142],[584,55],[417,175],[439,392],[548,55],[714,701],[643,71],[357,69],[649,459],[789,541],[626,5],[752,619],[711,267],[639,12],[750,364],[620,249],[769,721],[636,97],[233,15],[171,72],[488,421],[251,139],[750,98],[199,64],[768,344],[759,537],[435,154],[425,185],[336,221],[418,395],[390,136],[618,603]] : You can finish all the classes.

2015/8/10

### LeetCode 拓扑排序题目解析 #### 课程表 (Course Schedule)LeetCode上的经典问题之一是《课程表》[^4]。该问题描述如下: 给定 `n`门课程以及一些先修课的要求,判断是否可以完成所有课程的学习。 ##### 思路分析 这个问题可以通过检测是否存在有向无环图(DAG)来解决。具体来说,如果能够找到一种拓扑排序方式,则意味着这些课程是可以按照一定顺序全部学完的;反之如果有环存在,则无法完成所有的课程学习。 为了实现这一点,通常会采用邻接矩阵或者邻接表的形式构建图结构,并利用深度优先搜索(DFS)[^2] 或广度优先搜索(BFS)[^1] 来尝试获得一个有效的拓扑序列。 对于BFS方法,在初始化阶段需要找出入度为零的节点加入队列中作为起点,之后不断移除当前处理过的节点并更新其他相连节点的入度直到遍历结束或发现矛盾为止[^5]。 ```java public boolean canFinish(int numCourses, int[][] prerequisites) { List<Integer>[] adj = new ArrayList[numCourses]; int[] indegrees = new int[numCourses]; // 构建邻接表和计算各结点入度数 for (int[] edge : prerequisites) { if (adj[edge[1]] == null) adj[edge[1]] = new ArrayList<>(); adj[edge[1]].add(edge[0]); ++indegrees[edge[0]]; } Queue<Integer> queue = new LinkedList<>(); // 将所有入度为0的顶点入队 for (int i = 0; i < numCourses; ++i){ if(indegrees[i]==0)queue.offer(i); } while(!queue.isEmpty()){ Integer cur=queue.poll(); --numCourses; if(adj[cur]!=null){ for(Integer next:adj[cur]){ if(--indegrees[next]==0){ queue.offer(next); } } } } return numCourses==0; } ``` 这段代码实现了基于Kahn算法(即宽度优先搜索)来进行拓扑排序的过程。它首先统计每个节点的入度数目,并把那些没有任何前驱依赖关系(也就是入度等于0)的节点放进初始队列里。接着逐个取出队首元素进行访问操作——减少其指向的目标节点们的剩余未满足条件数量(即减去它们各自的入度值)。一旦某个目标节点变得不再受约束(它的新入度变为0),就立即将这个节点追加到待处理集合当中继续考察下去。最终当整个流程结束后,只要还剩下没被触及过的东西就意味着原图中含有至少一个闭环路径,从而导致任务失败;否则便成功找到了一组可行方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值