875. Koko Eating Bananas
有一堆香蕉,每组数量不定,koko每小时只能吃k个香蕉,且每小时只能吃一个组中的香蕉,即一小时内如果某组香蕉吃完了,那也只能干等着。求最小的k使得koko能在给定的H小时内吃完所有香蕉
主要是这么几步:
- 先确定区间,最少是1,最大就是数组中最大值
- 用二分法每次猜一个k,然后看看能不能在H小时内吃完,来重新设置l 和 r的值,这里用lower_bound,因为要求的是 大于等于target的一个数
/*
时间复杂度:O(n*lg(m))
空间复杂度:O(1)
n是数组长度,m是数组最大值
*/
public int minEatingSpeed(int[] piles, int H) {
int maxPiel = 0;
for (int i : piles) {
if (maxPiel < i)
maxPiel = i;
}
int l = 1, r = maxPiel;
while (l < r) {
int m = l + (r - l) / 2;
if (spendTime(piles, m) <= H)
r = m;
else
l = m + 1;
}
return l;
}
public int spendTime(int[] piles, int k) {
int totalTime = 0;
for (int i : piles) {
totalTime += (i + k - 1) / k;
}
return totalTime;
}
1011. Capacity To Ship Packages Within D Days
求最少的一个装货量,使得能在D天内把所有的包运到目的地。
和上面那题很像,都是lower_bound二分法不断试值,但有几个不同处:
- 货物不能拆分,所以装货量必须大于等于最大的那个包,同时因为D小于包的数量,那么D就有可能是一天,所以装货量最大可能值是包的总和
- 因此区间和上面那题不一样,l是最大的那个包,r是所有包的总和
- 还有一点是在计算每个装货量所花费天数时,一些计算方法要注意,直接看代码吧
public int shipWithinDays(int[] weights, int D) {
int max = 0, sum = 0;
for (int i : weights) {
if (i > max)
max = i;
sum += i;
}
int l = max, r = sum;
while (l < r) {
int m = l + (r - l) / 2;
if (spendDays(weights, m) <= D)
r = m;
else
l = m + 1;
}
return l;
}
public int spendDays(int[] weights, int capacity) {
int total = 1, once = 0;
for (int i = 0; i < weights.length; i++) {
//注意这里
if (once + weights[i] > capacity) {
total++;
once = 0;
}
once += weights[i];
}
return total;
}