leetcode:630. 课程表 III

题目来源

题目描述

在这里插入图片描述

class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) {

    }
};

题目解析

分析

  • 假如给定了两门截止时间不同的课程,我们应该如何学习呢?
  • 带入到现实中,我们肯定先学习截止时间更近的课程,比如,一门课程在10天后截止,另一门在100天后截止,你肯定会先学习10天后截止的那门课程,对不对?
    • 比如说,给定的两门课程为:[1, 3] 和 [2, 5],这时候,我们无论先学习哪门课程都是可以完成两门课程的。
    • 再比如说,给定的两门课程为:[1, 2] 和 [2, 4],这时候,如果先学习后者再学习前者,会导致 d2 + d1 > l1,将无法完成前者的学习,因此,我们只能先学习前者再学习后者。
  • 因此,我们可以先将所有课程按照截止时间排序,然后依次学习
  • 但是,这样并不能保证我们前面遍历到的课程学习了,后面的课程就一定能够学习。
    • 比如说,给定了三门课程分别为:[1,2] 、[3, 4]、[2, 5],这时候,当选择到第三门课程的时候,发现 1 + 3 + 2 > 5 的,所以,第三门课程是学习不了的,那么,这时候,在第二门和第三门课程中间做一个选择,你会怎么选择呢?(因为后面可能还有个 [3, 6] 的课程)
    • 因为题目中要求了返回能够学习的最大数目,所以我们应该优先学习时长更短的课程。对于上例来说,我们选择 [2, 5] 优于 [3, 4],因为 [2, 5] 学习时长更短,相当于我们可以有更多的时间学习后续的课程。
  • 因此,我们可以使用优先队列来维护已经选择了的课程,当出现冲突时,我们比较堆顶元素与待选择元素的学习时长,选择时长更短的课程学习

算法:

  • 先按照截止时间升序排序
  • 然后依次遍历一个课程(用优先队列维护已选课程),当遍历到 ( t i , d i ) (t_i, d_i) (ti,di)时:
    • 如果当前优先队列中所有课程的总时间与 t i t_i ti之和小于等于 d i d_i di,那么就将 t i t_i ti放入优先队列中
    • 如果当前优先遍历中所有课程的总时间与 t i t_i ti之和大于 d i d_i di,那么我们找到优先队列中的最大元素 t m t_m tm,如果 t m > t i t_m > t_i tm>ti,替换掉
  • 最终优先队列的长度就是我们能最多修习的课程
class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) {
        sort(courses.begin(), courses.end(), [](const auto &a, const auto &b){
            return a[1] < b[1];
        });
        
        std::priority_queue<int> q;
        int total = 0;  // 优先队列中所有课程的总时间
        
        for(auto c : courses){
            int ti = c[0], di = c[1];
            if(total + ti <= di){
                total += ti;
                q.push(ti);
            }else if(!q.empty() && q.top() > ti){
                total -= q.top() - ti;
                q.pop();
                q.push(ti);
            }
        }
        return q.size();
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值