算法-Course Schedule-课程表

本文介绍了如何解决Course Schedule问题,通过有向图表示课程之间的先修关系,并利用拓扑排序来确定修课顺序。在拓扑排序过程中,统计每个节点的入度并用队列处理入度为0的节点,确保无环且满足先修条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目描述

你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
 
示例 1:
输入: 2, [[1,0]] 
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。

2、题目分析

  • 修一门课之前需要满足这门课的先修课程已经修完

  • 每次先修完哪些课程呢?第一个肯定是没有先修课程的那个,之后选出先修课程已修完的

  • 如何表示课程之间的关系呢?使用有向图,[0,1]表示0的先修课程是1,那么1->0就表示这俩的关系,0有个入度为1

  • 如果图中有环则该环的节点都不能取,只有当节点的入度==0的时候才能取这个点,之后相关的节点入度-1

  • 拓扑排序:对DAG的顶点进行排序,使得每条有向边(u,v),在排序记录中u比v先出现

    1、统计每个节点的入度生成入度表indegrees

    2、将所有入度为0的点入队,队列非空时依次出队

    ​ --将此节点pre的所有邻接节点的入度-1,indegrees[cur] -= 1;

    ​ --入度=0的节点入队

    ​ --每当由pre节点出队时,numCourses–

3、代码实现

 public boolean canFinish(int numCourses, int[][] prerequisites){
     int[] indegress = new int [numCourses];//入度表
     List<List<Integer>> list = new ArrayList<>();//邻接表
     for(int i = 0;i < numCourses;i++){
         list.add(new ArrayList<>());
     }
     for(int[] prerequisite : prerequisites){
         indegress[prerequisite[0]]++;//该顶点的入度+1
         list.get(prerequisite[1]).add(prerequisite[0]);//记录该顶点指向的所有节点
     }
     Queue<Integer> queue = new LinkedList<>();
     for(int i = 0;i < numCourses;i++){//0度顶点入列
         if(indegress[i] == 0) queue.add(i);
     }
     while(!queue.isEmpty()){
         int pre = queue.poll();
         numCourses--;
         for(int cur : list.get(pre)){//该顶点的后驱顶点入度-1
             indegress[cur]--;
             if(indegress[cur] == 0) queue.add(cur);
         }

     }
     return numCourses == 0;
 }

4、复杂度分析

  • 时间复杂度:O(N + M),其中N为课程数,M为先修课程的要求数。这其实就是对图进行广度优先搜索的时间复杂度。
  • 空间复杂度:O(N + M)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值