[M贪心] lc881. 救生艇(贪心+贪心证明)

1. 题目来源

链接:881. 救生艇

2. 题目解析

常规的一道贪心,思路很简单,关键仍旧是贪心思路的证明。

思路:

  • 排序,尽量让重的和轻的组成一个救生艇。
  • 即,每次都会将末尾最终的安排掉。
  • 注意可能会造成 i=j 的情况,即最终仅剩余一人,那么只需要安排一条船即可。不论这个人的两倍是否大于 limit,无关紧要,反正他仅需一条船。
  • 例如 people = [3,2,2,1], limit = 3 这个样例,最终 a[i]=a[j]=2for 循环判出条件如果直接写成 i<j 的话,就漏掉了 2 这个人,所以要写成 i<=j,反正不管如果,都只还要一条船来接 2。

证明:

  • 证明思路仍旧:主要证明任给一个最优解可以通过调整,在答案不变差的情况下,调整为贪心解。
  • 当记末尾人重为 d,开头人重为 a。如果 a+d>limit,那么 d 只能自己坐一艘船,和贪心解一致。
  • 如果 a+d<=limit。贪心解中,a、d 坐同一艘船,最优解有两种情况。
    • d 自己坐一艘船。那么 a 不论是自己坐一艘船还是和别人同坐另一艘船。调整 ad 同坐,一定是更好的结果,结果不会变差。
    • d 和其他人坐一艘船,假设为 c。显然此时,c>=a,所以,不论 a 自己坐,还是 a 和别人坐,都可以将 a、c 调换,让 ad 坐同一艘船。并且重量是变少了,ca 的另一个人也少满足重量限制的。
  • 综上,一定可以将最优解,在答案不变差的情况下,将坐船顺序调整为贪心解。那么贪心解就是一个最优解。

实现的时候,每次都安排末尾的人,所以尾指针顺次向前走就行。答案每次都 +1,不论是自己坐一艘船还是和前面的人坐一艘。注意循环跳出条件,i<=j,原因在上面已经提过了。


  • 时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
  • 空间复杂度 O ( 1 ) O(1) O(1)

class Solution {
public:
    int numRescueBoats(vector<int>& people, int limit) {
        sort(people.begin(), people.end());

        int res = 0;
        for (int i = 0, j = people.size() - 1; i <= j; j -- ) {
            if (people[j] + people[i] <= limit) i ++ ;
            res ++ ;
        }

        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值