630. 课程表 III

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:贪心+优先队列
  • 写在最后

Tag

【贪心】【优先队列】【数组】


题目来源

630. 课程表 III

630. 课程表 III_第1张图片

题目解读

n 门编号从 1n 的课程,有一个数组 courses,其中 courses[i] = [duration, lastDay] 表示第 i 门课将会持续上 duaration 天,并且必须在 lastDay 之前完成(包括这一天)。你的学期从第一天开始,且不能同时上两门及以上的课程,返回你最多可以修完多少门课程。


解题思路

方法一:贪心+优先队列

为了尽可能多的学习课程,我们优先学习 lastDay 靠前的课程。如果当前课程的结束时间和 lastDay 有冲突了,并且前面学习过的课程中持续时间最长的课程持续时间大于当前课程,就用当前课程替换掉学习过的课程中持续时间最长的课程。

具体地,首先需要对 courses 课程进行按照 lastDay 字段进行升序排序;接着维护一个优先队列 q 用来存放可以学习的课程,如果遇到冲突,直接 q.top() 取出的就是学习过的课程中持续时间最长的课程,如果学习过的课程中持续时间最长的课程的持续时间大于当前课程的持续时间,则用当前课程的持续时间替换之。最后返回 q 的长度即为可以学习的课程数量的最大值。

实现代码

class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) {
        sort(courses.begin(), courses.end(), [](const auto& c1, const auto& c2) {
            return c1[1] < c2[1];  
        });

        priority_queue<int> q;
        int total = 0;      // 学习过课程的总时间节点
        for (const auto& course : courses) {
            int t = course[0], d = course[1];
            if (total + t <= d) {
                total += t;
                q.push(t);
            }
            else if (!q.empty() && q.top() > t) {
                total -= q.top();
                total += t;
                q.pop();
                q.push(t);
            }
        }
        return q.size();
    }
};

复杂度分析

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn),排序需要的时间为 O ( n l o g n ) O(nlogn) O(nlogn)。优先队列单次需要 O ( l o g n ) O(logn) O(logn) 的时间,每个课程最多被取出或放入队列一次,因此时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。总的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

空间复杂度: O ( n ) O(n) O(n),是优先队列需要使用的空间。


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 哦。

你可能感兴趣的:(LeetCode每日一题,贪心,优先队列,c++,算法)