LeetCode #207 - Course Schedule - Medium

来源:互联网 发布:arp scan python 编辑:程序博客网 时间:2024/04/30 03:43

Course Schedule Series

Course Schedule I: http://blog.csdn.net/Arcome/article/details/53790947

Course Schedule II: http://blog.csdn.net/Arcome/article/details/53791005

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 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?

Note:

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

Hints:

  • 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.
  • Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
  • Topological sort could also be done via BFS.

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.

Algorithm

整理一下题意:给定一组课程,课程之间有先修或后修的关系,要求判断能否修完给定的全部课程。
输入数据格式:给定整数numCourses和向量prerequisites:整数numCourses表示所有课程的数量;向量prerequisites包含一组pair格式的数据,如pair(a,b)表示修课程a前需要先修课程b。

可以抽象为图问题。numCourses表示图中的点数,向量prerequisites的每个元素都是一个pair,pair(a,b)由b指向a的一条边。于是可以得到一个有向图G。题目要求判断能否修完所有课程,即判断能否对所有点进行拓扑排序。若能对图G中所有点作拓扑排序,说明G中所有点都有前后关系,即不存在环。于是问题可以转化为判断图G是否存在环。

下面给出判断图G是否存在环的算法。使用到的数据结构为向量和队列。

  1. 先由输入数据建一张图,以邻接表进行存储。向量graph的每个元素graph[i]表示与节点i指向的所有节点的情况,如graph[i][j]存储了节点i指向的某个点的值。

  2. 建立邻接表过程中,同时更新每个点的入度。当某个点加入graph[i]向量时,该点的入度加一。

  3. 将图中所有入度为0的点加入到队列q中,作为遍历的起点。

  4. 若队列q非空,则取出队首元素,表示从图中删去该节点。由于删去了该节点,所以需要更新图中队首节点指向的节点的入度。更新后,若节点的入度为0,则加入队列。

  5. 重复步骤4直到队列为空。此时,由于图中所有入度为0的节点已通过拓扑排序的过程删去,故剩余的图为空图或环。此时再判断一次所有点的入度,若存在点入度不为0,说明剩余图中存在环,即原图包含环,于是不能修完所有课程,返回false。若所有节点入度均为0,说明剩余图为空图,不包含环,于是可以修完所有课程,返回true。

代码如下。

class Solution {public:    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {        vector<vector<int>> graph(numCourses,vector<int> (0));        vector<int> in(numCourses,0);        for(int i=0;i<prerequisites.size();i++){            graph[prerequisites[i].second].push_back(prerequisites[i].first);            in[prerequisites[i].first]++;        }        queue<int> q;        for(int i=0;i<in.size();i++){            if(in[i]==0) q.push(i);        }        while(!q.empty()){            int p=q.front();            q.pop();            for(int i=0;i<graph[p].size();i++){                in[graph[p][i]]--;                if(in[graph[p][i]]==0) q.push(graph[p][i]);            }        }        for(int i=0;i<in.size();i++){            if(in[i]!=0) return false;        }        return true;    }};
0 0
原创粉丝点击