LeetCode 630. 课程表 III

630. 课程表 III

 

【贪心+排序+优先队列】ci = [di, li],假设存在1,2,3...这样的顺序使得最后产生最优解,那么需要s012:

0 + d0 < l0

0 + d0 + d1 < l1

0 + d0 + d1 + d2 < l2...

如果将0和1交换顺序,那么就变成了s10:

0 + d1 < l1

0 + d1 + d0 < l0

如果在s10成立的情况下s01必然成立(因为s01是最优解,在其他情况下也必须成立)那么我们需要把s01的右边的条件放更宽,需要l1 > l0。验证一下:0 + d1 + d0 < l0成立,因为l1 > l0,那么0 + d1 + d0 < l1必然也成立,0 + d1 + d0 < l0成立,那么0 + d0 < l0必然也成立。

所以按照l进行排序更容易找到最优排列。在已经拍好前i - 1个的情况下,当前为第day天,如果day + di < li,那么第i个可以直接排在后面,并且把day + di;否则,我们应该看看他的d是否比之前序列中的某个d小,这样可以使得总的day更小,更容易比后面的l小。

class Solution {

    // 贪心
    // 2:32 3:47
    // 1 + d0 < l0
    // 1 + d0 + d1 < l1
    // 1 + d0 + d1 + d2 < l2
    
    // 1 + d0 + d2 < l2
    // 1 + d0 + d2 + d1 < l1 

    public int scheduleCourse(int[][] courses) {
        PriorityQueue<int[]> queue = new PriorityQueue<int[]>((a, b) -> b[0] - a[0]);
        Arrays.sort(courses, (a, b) -> a[1] - b[1]);
        int day = 0;
        for (var c: courses) {
            if (day + c[0] <= c[1]) {
                day += c[0];
                queue.offer(c);
            } else {
                if (!queue.isEmpty()) {
                    var top = queue.peek();
                    if (top[0] > c[0]) {
                        day = day - top[0] + c[0];
                        queue.poll();
                        queue.offer(c);
                    }
                }
                
            }
        }
        return queue.size();
    }
}
class Solution {
public:

    // 4:13 23

    int scheduleCourse(vector<vector<int>>& courses) {
        sort(courses.begin(), courses.end(), [](const vector<int>& a, const vector<int>& b) {
            return a[1] < b[1];
        });
        priority_queue<int> q;
        int day = 0;
        for (auto c: courses) {
            if (day + c[0] <= c[1]) {
                day += c[0];
                q.push(c[0]);
            } else {
                if (!q.empty()){
                    auto top = q.top();
                    if (top > c[0]) {
                        q.pop();
                        q.push(c[0]);
                        day = day - top + c[0];
                    }
                }
            }
        }
        return q.size();
    }
};

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值