课程表---bfs
题目:
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
- 例如,先修课程对
[0, 1]表示:想要学习课程0,你需要先完成课程1。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
示例 1:
输入:numCourses = 2, prerequisites = [[1,0]] 输出:true 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:
输入:numCourses = 2, prerequisites = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
提示:
1 <= numCourses <= 20000 <= prerequisites.length <= 5000prerequisites[i].length == 20 <= ai, bi < numCoursesprerequisites[i]中的所有课程对 互不相同
思路:
本题可以转化为:课程安排是否是有向无环图。因为课程间规定了前置条件,但不能构成任何环路,否则课程前置条件将不成立。
思路是通过拓扑排序,判断此课程安排图是否是有向无环图。拓扑排序原理:对有向无环图的顶点进行排序。使得对每一条有向边(u,v),均有u(在排序记录中)比v先出现。亦可理解为对某点v而言,只有当v的所有源点均出现了,v才能出现。
通过课程前置条件列表prerequisites 可以得到课程安排图的邻接表adjacency,以降低算法时间复杂度,以下两种方法都会用到邻接表。
入度表(广度优先遍历)
1.统计课程安排图中每个节点的入度,生成入度表indegrees。
2.借助一个队列queue,将所有入度为0的节点入队。
3.当queue非空时,依次将队首节点出队,在课程安排图中删除此节点pre:
并不是真正的从邻接表删除此节点pre,而是将此节点对应所有邻接节点cur的入度-1,即indegrees[cur] -=1;
当入度-1后邻接节点cur的入度为0,说明cur所有的前驱节点已经被“删除”,此时将cur入队。
4.在每次pre出队时,执行numCourses--;
若整个课程安排图是有向无环图(即可以安排),则所有节点一定都入队并出队过,即完成拓扑排序。换个角度说,若课程安排图中存在环,一定有节点的入度始终不为 0。
因此,拓扑排序出队次数等于课程个数,返回 numCourses == 0 判断课程是否可以成功安排。
复杂度分析:
时间复杂度 O(N+M): 遍历一个图需要访问所有节点和所有临边,N 和 M 分别为节点数量和临边数量;
空间复杂度 O(N+M): 为建立邻接表所需额外空间,adjacency 长度为 N ,并存储 M 条临边的数据。
class Solution{public boolean canFinish(int numCourses,int[][] prerequisites){int [] indegrees = new int[numCourses];List<List<Integer>> adjacency = new ArrayList<>();Queue<Integer> que = new LinkedList<>();for(int i = 0;i < numCourses;i ++){adjacency.add(new ArrayList<>());}for(int i = 0;i < prerequisites.length;i ++){int [] cp = prerequisites[i];indegrees[cp[0]]++;adjacency.get(cp[1]).add(cp[0]);}for(int i = 0;i < numCourses;i ++)if(indegrees[i]==0) que.add(i);while(!que.isEmpty()){int pre = que.poll();numCourses--;for(int i = 0;i < adjacency.get(pre).size();i++){int cur = adjacency.get(pre).get(i);indegrees[cur]--;if(indegrees[cur] == 0){que.add(cur);}}}return numCourses == 0;}
}
