LeetCode 1665. 完成所有任务的最少初始能量(排序+二分)

题意:
给你一个任务数组 tasks ,其中 tasks[i] = [actuali, minimumi] :

actuali 是完成第 i 个任务 需要耗费 的实际能量。
minimumi 是开始第 i 个任务前需要达到的最低能量。
比方说,如果任务为 [10, 12] 且你当前的能量为 11 ,那么你不能开始这个任务。
如果你当前的能量为 13 ,你可以完成这个任务,且完成它后剩余能量为 3 。

你可以按照 任意顺序 完成任务。

请你返回完成所有任务的 最少 初始能量。

数据范围:
1 <= tasks.length <= 105
1 <= actual​i <= minimumi <= 104
解法:
最少初始能量容易想二分,然后O(n)check.(虽然也有不二分的做法)
难点在于如何决定最优的做任务顺序.

设i[1]为第i个任务的最低能量,i[0]为第i个任务的实际能量,
正确的排序方式是按照i[0]-i[1]从小到大排序.

本来口胡了排序的证明,写完发现好像不太对又删掉了...
挂一个别人的证明算了...

注意点:直接auto会超时,得用auto&.

排序正确性的严格证明:this

code:
class Solution {
public:
    bool check(int mid,const vector<vector<int>>& a){
        for(const auto& i:a){
            if(mid<i[1])return 0;
            mid-=i[0];
        }
        return 1;
    }
    int minimumEffort(vector<vector<int>>& a){
        sort(a.begin(),a.end(),[](const vector<int>& a,const vector<int>& b){
            return a[0]-a[1]<b[0]-b[1];
        });
        int l=0,r=1e9;
        int ans=0;
        while(l<=r){
            int mid=(l+r)/2;
            if(check(mid,a))ans=mid,r=mid-1;
            else l=mid+1;
        }
        return ans;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值