7.爱吃香蕉的珂珂
leetcode875题
珂珂喜欢吃⾹蕉。这⾥有 N 堆⾹蕉,第 i 堆中有 piles[i] 根⾹蕉。警卫已经离开了,将在
H ⼩时后回来。珂珂可以决定她吃⾹蕉的速度 K(单位:根/⼩时)。每个⼩时,她将会选择⼀堆⾹蕉,从中吃掉 K 根。如果这堆⾹蕉少于 K 根,她将吃掉这堆的所有⾹蕉,然后这⼀⼩时内不会再吃更多的⾹蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的⾹蕉。计算她可以在 H ⼩时内吃掉所有⾹蕉的最⼩速度K(K 为整数)。
基本思路:求最值问题也就是求边界问题,可以把二分法需要查找的变量映射到具有单调性的函数上,自变量是什么?要求的东西就是自变量,本题就是吃香蕉的速度k,因变量是吃香蕉用的时间,约束条件target是警卫离开的时间H。也就是在警卫离开的时间内吃完香蕉速度集合的左边界。
映射函数
```Java
//时间函数
//定义:速度为 x 时,需要 f(x) 小时吃完所有香蕉
public static long f(int[] piles, int x){
long hours=0;
for(int i=0;i<piles.length;i++){
hours+=piles[i]/x;
if(piles[i]%x>0){
hours++;
}
}
return hours;
}
```
求左边界
```Java
public static int minEatingSpeed(int[] piles, int H){
int left=0;int right=1000000000;
while(left<=right){
int mid=left+(right-left)/2;
if(mid==0||H<f(piles,mid)){
left=mid+1;
}else if(H>=f(piles,mid)){
right=mid-1;
}
}
return left;
}
```
这里需要注意的一个问题是当右边界一直收缩到零的时候会出现除零异常,很显然珂珂吃香蕉的速度不可能为零,这里就需要mid==0的时候进行判断。
8.在 D 天内送达包裹的能⼒
leetcode1101题
要求:传送带上的第 i 个包裹的重量为 weights[i],运输船每天都会来运输这些包裹,每天装载的包裹重量之和不能超过船的最⼤运载重量。如果要在 D 天内将所有包裹运输完毕,求运输船的最低运载能⼒。
这道题与上道题一样也是考察二分搜索的左边界问题。
target约束D天,自变量运输船的运载能力,因变量包裹需要花多少天运输完。
映射函数:
```Java
//时间函数
//定义:运载能力为 x 时,需要 f(x) 天运送玩所有货物
public static int f1(int[] weights,int x){
int days=0;
for(int i=0;i<weights.length;){
int cat=x;
while(i<weights.length){
if(cat<weights[i])break;
else cat-=weights[i];
i++;
}
days++;
}
return days;
}
```
```Java
public static int shipWithinDays(int[] weights,int days){
int left=0;int right=0;
//运载能力最小值要大于等于最重包裹的重量,运载能力最大值所有包裹的重量,也就是一天
for (int w : weights) {
left = Math.max(left, w);
right += w;
}
while (left<=right){
int mid=left+(right-left)/2;
if(days>=f1(weights,mid)){
right=mid-1;
}
else if(days<f1(weights,mid)){
left=mid+1;
}
}
return left;
}
```
这里需要注意的是左右区间要满足一定的条件。
大家好呀,借助哎吃香蕉的珂珂和在D天内运送包裹的能力两道题讨论了一下泛型二分问题,总结了一个套路,一般有单调函数和求边界问题基本都是泛型二分问题,解题思路首先找自变量(所求),然后得到因变量,最后得到满足约束target的边界值。其中要注意递减函数与区间的收缩相反,起始区间可能需要满足一些条件。