题目描述
传送带上的包裹必须在 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;
}
}