leetcode--Boats to Save People

博客围绕用船救人问题展开,给定人的重量数组和船载重限制,求最少船数。先分析暴力破解复杂度高,后探讨简化算法,提出贪心策略,即最大最小数字组合,并用反证法证明其最优,最后给出时间复杂度为O(nlogn)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:给定数组表示人的重量,现在用船去救这些人,每条小船载重限制为limit,最多坐两个人,求最少需要多少条小船?

分析:
(1)假如一开始就知道了这道题是使用贪心策略,其实还比较简单。最大最小的匹配尝试并证明一下就行了。但是一开始,不太容易往贪心上考虑。
(2)先来看看暴力破解,我们可以尝试将所有的people两人一组组队,这样一共会有大约(n-1)(n+1)/4中组队的情况,这里排列组合就不详细分奇偶讨论了。组队完成后,将不满足要求的组合拆开,看看最后哪种组合剩下的队伍最少。这样组队其实复杂度相当高。
(3)我们看看这个过程里都有哪些多余的步骤可以简化算法:

  • 第一点,对于那些大于limit/2的people,彼此之间是无法组队的
  • 基于第一点,我们考虑到较大的数字选择其实比较少,对于它们我们可以先考虑。而对于那些不大于limit/2的数字,任意组合都没有问题。
  • 现在为一个最大的不超过limit的元素挑选队友,想到这里,贪心策略就不是很突兀了,我想试试会不会那些不超过limit的最大的数字,和当前未匹配的最小的数字组合就是答案呢?

证明:假设max是小于limit的最大数字,min是所有元素中最小的数字,如果max+min≤limitmax+min \leq limitmax+minlimit则它们搭配是最优的。
反证法:假设存在更优的情况,max,和min没有搭配在一起。

  • 首先在这个最优解中,这两个人不能落单,否则将它们组合在一起,情况不会变差。
  • 假设最有组合中,max与x组合,min与y组合;那么有
    max+x≤limitmax+x \leq limitmax+xlimit
    max≥ymax \geq ymaxy 是已知的。所以
    y+x≤limity+x \leq limity+xlimit
    也成立。
    到这里,假如我们将最优组合中的(max,x)(min,y)换成(max,min)(x,y)同样是一个最优解。
    所以最大最小的搭配能够产生最优解。其实,只要让那些能匹配的大值元素不落单,都是最优解。
    时间复杂度:
    最大最小搭配需要排序,排序后两个指针双向遍历即可。
    复杂度:O(nlogn)O(nlogn)O(nlogn)
    代码:
 public int numRescueBoats(int[] people, int limit) {
	        int rs = people.length;
	        Arrays.sort(people);
            int pre = 0,latter = people.length-1;
            while(pre<latter){
                if(people[latter--]+people[pre]<=limit){
                    pre++;
                    rs--;
                }
            }
	        return rs;
	    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值