leetcode 630 课程表

给定一组在线课程的时间和关闭日期,你需要找出最多可以修的课程数量。课程必须连续进行,并且要在截止日期前完成。例如,对于输入 [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]],答案是 3。解决此问题需要对课程进行排序并维护一个已选课程的堆。" 115241398,7868319,解决Linux上appium无法启动的问题,"['Linux', 'appium']

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

There are n different online courses numbered from 1 to n. Each course has some duration(course length) t and closed on dth day. A course should be taken continuously for t days and must be finished before or on the dth day. You will start at the 1st day.

Given n online courses represented by pairs (t,d), your task is to find the maximal number of courses that can be taken.

Example:

Input: [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]
Output: 3
Explanation: 
There're totally 4 courses, but you can take 3 courses at most:
First, take the 1st course, it costs 100 days so you will finish it on the 100th day, and ready to take the next course on the 101st day.
Second, take the 3rd course, it costs 1000 days so you will finish it on the 1100th day, and ready to take the next course on the 1101st day. 
Third, take the 2nd course, it costs 200 days so you will finish it on the 1300th day. 
The 4th course cannot be taken now, since you will finish it on the 3300th day, which exceeds the closed date.

这里有 n 门不同的在线课程,他们按从 1 到 n 编号。每一门课程有一定的持续上课时间(课程时间)t 以及关闭时间第 d 天。一门课要持续学习 t 天直到第 d 天时要完成,你将会从第 1 天开始。

给出 n 个在线课程用 (t, d) 对表示。你的任务是找出最多可以修几门课。

 

示例:

输入: [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]
输出: 3
解释: 
这里一共有 4 门课程, 但是你最多可以修 3 门:
首先, 修第一门课时, 它要耗费 100 天,你会在第 100 天完成, 在第 101 天准备下门课。
第二, 修第三门课时, 它会耗费 1000 天,所以你将在第 1100 天的时候完成它, 以及在第 1101 天开始准备下门课程。
第三, 修第二门课时, 它会耗时 200 天,所以你将会在第 1300 天时完成它。
第四门课现在不能修,因为你将会在第 3300 天完成它,这已经超出了关闭日期。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/course-schedule-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

解题思路:

      看完题目首先的思路是先考虑截止日期早的课程,所以调用sort函数将courses向量重排一遍。

      遍历向量中的所有课程,如果已花时间加上课程时间大于当前课程的截止时间,那就将已选课程中最大的课程持续时间与当前课程持续时间比较,选择较小的那门课程,这样所选课程总数不变,但是所花时间更少。所以需要维持一个已选课程的堆。

class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) 
    {
        if(courses.size() == 0) return 0 ;
        sort(courses.begin() , courses.end() , [](const auto a , const auto b)
             {
                 return a[1] < b[1] ;
             });
        
        priority_queue<int> cour ; //参加的课程
        int time = 0 ; //所花的全部时间
        
        for(const auto cor : courses)
        {
            if(time + cor[0] <= cor[1])
            {
                time += cor[0] ;
                cour.push(cor[0]) ;
            }
            else if(!cour.empty() && cour.top() > cor[0])
            {
                time += cor[0] - cour.top() ; 
                cour.pop() ;
                cour.push(cor[0]) ;
            }
        }
        
        return cour.size() ;
    }
};

向算法传递函数,可以传递函数,函数指针,lambda表达式以及函数对象。这些都属于可调用对象,可以对其使用函数调用运算符。

sort(courses.begin() , courses.end() , [](const auto a , const auto b)
             {
                 return a[1] < b[1] ;
             });

这个使用的是lambda表达式。

### 关于LeetCode课程表的理解 #### 解决方案概述 对于LeetCode上的课程表问题,解决方案主要围绕图论中的拓扑排序展开。通过构建有向无环图(DAG),可以有效判断是否存在一种顺序能够完成所有的前置条件并修完所有课程[^1]。 #### 数据结构的选择 为了表示这种依赖关系,采用`collections.defaultdict(list)`来创建邻接列表形式的图模型,其中键代表某一门课,而对应的值则是一个列表,记录着该课程作为先修课所指向的所有后续课程。此外,还维护了一个入度数组`indeg`用于追踪每门课程被多少其他课程视为前提条件[^2]。 ```python edges = collections.defaultdict(list) indeg = [0] * numCourses for info in prerequisites: edges[info[1]].append(info[0]) indeg[info[0]] += 1 ``` 这段代码初始化了上述提到的数据结构,并依据输入参数`prerequisites`填充它们的内容。这里`prerequisites`是由若干二元组组成的列表,每个二元组描述了一种特定的前后置关系。 #### 拓扑排序算法实现 基于Kahn's Algorithm的思想,在遍历过程中始终选取那些当前没有任何未满足前导条件(即入度为零)的节点加入队列中处理;每当访问到一个新的顶点时,则将其相邻结点们的入度减一,以此模拟移除了这条边的效果。当某条路径上最后一个可选节点也被探索完毕之后,如果此时已经累计访问过全部N个节点(`visited == numCourses`)就说明存在合法的学习序列。 ```python q = collections.deque([u for u in range(numCourses) if indeg[u] == 0]) visited = 0 while q: visited += 1 u = q.popleft() for v in edges[u]: indeg[v] -= 1 if indeg[v] == 0: q.append(v) return visited == numCourses ``` 此部分实现了完整的广度优先搜索过程以及最终的结果判定逻辑。 #### 学习策略建议 针对此类涉及复杂数据结构和算法设计的问题,推荐采取分阶段深入理解的方式: - **基础概念掌握**:熟悉基本术语如图、树及其性质; - **具体案例分析**:尝试手动绘制几个小型实例帮助直观感受整个流程; - **编程实践训练**:利用在线平台提供的测试环境反复调试直至完全弄懂为止; - **拓展延伸思考**:考虑如何优化现有方法或者解决更复杂的变体版本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值