二分搜索运用
题1:
1011. 在 D 天内送达包裹的能力labuladong 题解思路
传送带上的包裹必须在 days
天内从一个港口运送到另一个港口。
传送带上的第 i
个包裹的重量为 weights[i]
。每一天,我们都会按给出重量(weights
)的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。
返回能在 days
天内将传送带上的所有包裹送达的船的最低运载能力。
示例 1:
输入:weights = [1,2,3,4,5,6,7,8,9,10], days = 5 输出:15 解释: 船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示: 第 1 天:1, 2, 3, 4, 5 第 2 天:6, 7 第 3 天:8 第 4 天:9 第 5 天:10 请注意,货物必须按照给定的顺序装运,因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。
示例 2:
输入:weights = [3,2,2,4,1,4], days = 3 输出:6 解释: 船舶最低载重 6 就能够在 3 天内送达所有包裹,如下所示: 第 1 天:3, 2 第 2 天:2, 4 第 3 天:1, 4
示例 3:
输入:weights = [1,2,3,1,1], D = 4 输出:3 解释: 第 1 天:1 第 2 天:2 第 3 天:3 第 4 天:1, 1
提示:
1 <= days <= weights.length <= 5 * 104
1 <= weights[i] <= 500
1 class Solution { 2 public int shipWithinDays(int[] weights, int days) { 3 int l=0,r=1; 4 for (int w:weights){ 5 l=Math.max(l,w); 6 r+=w; 7 } 8 while (l<r) { 9 int mid=(l+r)/2; 10 if (f(weights,mid)<=days){ 11 r=mid; 12 } 13 else if (f(weights,mid)>days) { 14 l=mid+1; 15 } 16 } 17 return l; 18 } 19 20 public int f(int[] w,int cap){ 21 int ans=1,t=cap; 22 for (int i=0;i<w.length;i++){ 23 if (t>=w[i]) { 24 t-=w[i]; 25 continue; 26 }else { 27 t=cap; 28 t-=w[i]; 29 ans++; 30 } 31 } 32 //System.out.println(cap+" "+ans); 33 return ans; 34 } 35 }
以运载量为自变量,则运载天数是关于自变量不增的函数, 下界为所有货物中的最大值,上界为所有货物的重量。以此进行二分搜索,搜索的满足天数要求的左边界。
题2:
875. 爱吃香蕉的珂珂labuladong 题解思路
难度中等珂珂喜欢吃香蕉。这里有 N
堆香蕉,第 i
堆中有 piles[i]
根香蕉。警卫已经离开了,将在 H
小时后回来。
珂珂可以决定她吃香蕉的速度 K
(单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 K
根。如果这堆香蕉少于 K
根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 H
小时内吃掉所有香蕉的最小速度 K
(K
为整数)。
示例 1:
输入: piles = [3,6,7,11], H = 8 输出: 4
示例 2:
输入: piles = [30,11,23,4,20], H = 5 输出: 30
示例 3:
输入: piles = [30,11,23,4,20], H = 6 输出: 23
提示:
1 <= piles.length <= 10^4
piles.length <= H <= 10^9
1 <= piles[i] <= 10^9
1 class Solution { 2 public int minEatingSpeed(int[] piles, int h) { 3 int l=1,r=1000000000+1; 4 while (l<r) { 5 int mid=(l+r)/2; 6 if (f(piles,mid)<=h){ 7 r=mid; 8 }else { 9 l=mid+1; 10 } 11 } 12 return l; 13 } 14 15 public int f(int[] nums,int x){ 16 int ans=0; 17 for (int num:nums){ 18 ans+=num/x; 19 if (num%x!=0) ans++; 20 } 21 return ans; 22 } 23 }
同理,转化为二分搜索左边界。