[LeetCode解题报告] 630. 课程表 III

[LeetCode解题报告] 630. 课程表 III

    • 一、 题目
      • 1. 题目描述
      • 2. 原题链接
    • 二、 解题报告
      • 1. 思路分析
      • 2. 复杂度分析
      • 3. 代码实现
    • 三、 本题小结

一、 题目

1. 题目描述

  1. 课程表 III

难度:困难

这里有 n 门不同的在线课程,按从 1n 编号。给你一个数组 courses ,其中 courses[i] = [durationi, lastDayi] 表示第 i 门课将会 持续durationi 天课,并且必须在不晚于 lastDayi 的时候完成。

你的学期从第 1 天开始。且不能同时修读两门及两门以上的课程。

返回你最多可以修读的课程数目。

示例 1:

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

示例 2:

输入:courses = [[1,2]]
输出:1

示例 3:

输入:courses = [[3,2],[4,3]]
输出:0

提示:

  • 1 <= courses.length <= 104
  • 1 <= durationi, lastDayi <= 104

2. 原题链接

链接: 630. 课程表 III

二、 解题报告

1. 思路分析

这题是力扣《课程表》系列里的题,别的题都是拓扑排序,就这题不是。
这题的思路是贪心+优先队列

  • 首先结束时间排序,我们选课的时候一定优先选结束时间早的,这个方案是最优的。这是贪心的思想。
  • 学第i门课时,我们总希望前i-1门课,用的时长最短,这样后续课程更有可能学完,这也是贪心。
  • 记录学完当前课程需要的总时间,新来一门课i时,如果当前总时间+本课需要的时间没超时,直接储存学这门课。
  • 否则,需要研究一下如果从已学的课里拿掉一门课,能不能把本门课学了,这样方案的分数其实是不变的,都是学了i-1门课;
  • 但是如果之前已学的课里有比时间比第i课短的,那么可以降低我们的学的总时长,对后续课程有好处。
  • 因此我们需要一个数据结构能储存已学课程且快速访问其中用时最大的课程:优先队列。
  • 最后已学课程总数量就是答案。
  • 剩下的看代码。
    [LeetCode解题报告] 630. 课程表 III_第1张图片

2. 复杂度分析

最坏时间复杂度O(nlog2n)

3. 代码实现

贪心+优先队列

class Solution:
    def scheduleCourse(self, courses: List[List[int]]) -> int:
        courses.sort(key=lambda x:x[1])
        ans = []
        cur = 0
        for d,l in courses:
            if not ans:  # 队列空直接把合法条件入队即可。
                if d<=l:
                    heapq.heappush(ans,-d)
                    cur = d
            else:  # 队列不空
                if cur + d <=l :  # 如果这门课可以学,直接入队能多学一门课,最优。
                    heapq.heappush(ans,-d)
                    cur += d
                else:             # 如果这门课不能学,研究一下是否有必要从已学课程里替换一门课。
                    if -ans[0] > d and cur + ans[0] +d <= l:
                        cur += ans[0] +d 
                        heapq.heapreplace(ans,-d)
        return len(ans)                

三、 本题小结

  1. 贪心题好难,优先队列要掌握!

你可能感兴趣的:(今天开刷leetcode,贪心算法,算法,leetcode)