在 D 天内送达包裹的能力(JAVA写法超详细解析)

D天内送达包裹能力JAVA写法

题目描述

传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。

传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/capacity-to-ship-packages-within-d-days
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

问题分析

此题的意思非常简单明确,就是找到在规定时间内能运送完全部货物的最低运载能力,本题的思路其实是采用二分查找,在两个边界中找分别记为左边界left和右边界right。
首先我们得明确,最小的包裹运输能力一定要大于等于包裹数组重量中的任意一个,因为如果小于其中一个数组那就卡壳运不出去啦,所以left左边界一定要大于数组中最大的数。右边界right则要小于等于所有包裹总质量,因为等于总质量一天就可以运完了,所以不需要D天。在这两个边界上我们通过对分查找mid的方法使得范围不断缩小。但是缩小范围有个前提:就是运输的时间天数要小于等于规定的天数D。所以我们需要增加一个判断函数,来判断在当前这个运输的量下是否能够满足运输天数,以例子来讲解。

示例

输入:weights = [1,2,3,4,5,6,7,8,9,10], D = 5
输出:15
解释:
船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示:
第 1 天:1, 2, 3, 4, 5
第 2 天:6, 7
第 3 天:8
第 4 天:9
第 5 天:10

按此输入来解析:第一步我们left设置为10,right设置为55。mid=(right+left)/2=32.
判断最小运载能力32是否能能够满足天数5天内运完。判断发现可以。
rigth=mid,此时rigth=32,右边界缩小。
继续判断,mid=(right+left)/2=21。
判断最小运载能力21是否能能够满足天数5天内运完。判断发现可以。继续缩小right。
rigth=mid,此时rigth=21,右边界缩小。
继续判断,mid=(right+left)/2=15。
判断最小运载能力15是否能能够满足天数5天内运完。判断发现可以。继续缩小right。
rigth=mid,此时rigth=15,右边界缩小。
继续判断,mid=(right+left)/2=12。
判断最小运载能力15是否能能够满足天数5天内运完。判断发现不可以。此时增大left。
left=left+1,然后同理直到发现left==right等于15的时候退出,发现最小运载量为15.
注:这里设置的是right=mid,而不是right=mid-1,因为有可能当前的mid就是最小的运输值
所以通过解析我们需要写一个判断函数,判断当前的运载量是否能满足D天内完成,第二个就是用二分的方法,将中间值mid不断的缩小。

题解代码

下面展示一些JAVA代码段。

class Solution {
    //判断最低运载能力为H的时候能否在D天内送达
    public boolean verification(int[] weights, int D, int H){
        //天数计数,初始化为1
        int count = 1;
        //每天的包裹总量
        int singleWeight = 0;
        for(int i = 0; i < weights.length; ++i){
            //累计包裹总量
            singleWeight += weights[i];
            //如果累计包裹总量singleWeight > H,天数+1
            if(singleWeight > H){
                ++count;
                singleWeight = weights[i];
            }
            //如果当前累计的天数count > D,说明当前H不满足条件,返回false
            if(count > D){
                return false;
            }
        }
        //说明当前H满足条件,返回true
        return true;
    }
    //从数组的最大元素开始遍历判断值i是否满足verification
    public int shipWithinDays(int[] weights, int D) {
        //二分查找 r = 数组的总和, l = 数组的最大值
        int r = Arrays.stream(weights).sum();
        int l = Arrays.stream(weights).max().getAsInt();
        //l < r
        while(l < r){
            //取中间值
            int mid = (l + r) >> 1;
            //如果mid满足verification,则逼近右指针
            if(verification(weights, D, mid)){
                //包括mid
                r = mid;
            }else{
                //逼近左指针,mid + 1
                l = mid + 1;
            }
        }
        //返回当前l就是最小的满足条件的值,即最低运载能力
        return l;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值