【LeetCode】1014. Capacity To Ship Packages Within D Days + 875. Koko Eating Bananas(二分搜索)
1014. Capacity To Ship Packages Within D Days
题目
A conveyor belt has packages that must be shipped from one port to another within D days.
The i-th
package on the conveyor belt has a weight of weights[i]
. Each day, we load the ship with packages on the conveyor belt (in the order given by weights
). We may not load more weight than the maximum weight capacity of the ship.
Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within D
days.
Example 1:
Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5
Output: 15
Explanation:
A ship capacity of 15 is the minimum to ship all the packages in 5 days like this:
1st day: 1, 2, 3, 4, 5
2nd day: 6, 7
3rd day: 8
4th day: 9
5th day: 10
Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed.
Example 2:
Input: weights = [3,2,2,4,1,4], D = 3
Output: 6
Explanation:
A ship capacity of 6 is the minimum to ship all the packages in 3 days like this:
1st day: 3, 2
2nd day: 2, 4
3rd day: 1, 4
Example 3:
Input: weights = [1,2,3,1,1], D = 4
Output: 3
Explanation:
1st day: 1
2nd day: 2
3rd day: 3
4th day: 1, 1
Note:
1 <= D <= weights.length <= 50000
1 <= weights[i] <= 500
思路
这题首先要明确要求的 “船容量” 的取值范围:
(1)最小值 smallest:最大的weight[i]
;
(2)最大值 largest :所有weight[i]
的和。
也就是说,最终求得的 capacity 的取值范围是 [smallset, largest]
,而具体是这个区间中的哪个值,则可以采用二分搜索。
代码
class Solution {
public:
// 该函数返回的是:如果船容量为a,则需要几天运完
int days(int a, vector<int>& weights) {
int i, j, k;
j = 1;
k = a;
for(i=0; i<weights.size(); ++i) {
if(k >= weights[i]) {
k -= weights[i];
}
else {
k = a - weights[i];
j++;
}
}
return j;
}
int bsearch(vector<int>& weights, int l, int r, int d) {
int mid = (l + r) / 2;
int k = days(mid, weights);
if(k < d) { // 如果所需天数小于d,说明船容量还可以更小
if(l < mid-1)
return bsearch(weights, l, mid-1, d);
else
return l;
}
else if(k > d) { //如果天数大于d,说明船容量不够大
if(mid+1 < r)
return bsearch(weights, mid+1, r, d);
else
return r;
}
return mid;
}
int shipWithinDays(vector<int>& weights, int D) {
int i, j, k, lar, ans;
ans = lar = 0;
for(i=0; i<weights.size(); ++i) {
ans += weights[i];
lar = max(lar, weights[i]);
}
j = bsearch(weights, lar, ans, D);
if(days(j, weights) > D) {
while(days(j, weights) > D) {
++j;
}
return j;
}
while(j - 1 >= lar && days(j-1, weights) <= D) {
j--;
}
return j;
}
};
Leetcode 的 875. Koko Eating Bananas 和该题类似。
875. Koko Eating Bananas
题目
Koko loves to eat bananas. There are N piles of bananas, the i-th
pile has piles[i] bananas. The guards have gone and will come back in H
hours.
Koko can decide her bananas-per-hour eating speed of K
. Each hour, she chooses some pile of bananas, and eats K
bananas from that pile. If the pile has less than K
bananas, she eats all of them instead, and won’t eat any more bananas during this hour.
Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back.
Return the minimum integer K
such that she can eat all the bananas within H
hours.
Example 1:
Input: piles = [3,6,7,11], H = 8
Output: 4
Example 2:
Input: piles = [30,11,23,4,20], H = 5
Output: 30
Example 3:
Input: piles = [30,11,23,4,20], H = 6
Output: 23
Note:
1 <= piles.length <= 10^4
piles.length <= H <= 10^9
1 <= piles[i] <= 10^9
思路
这题跟 1014 那题是一样的,可以采用二分搜索来做。
首先明确 K 的取值范围:
(1)最小 :1;
(2)最大:piles[i]
中的最大值。
明确范围后,就可以利用二分搜索了。
代码
class Solution {
public:
int gethours(vector<int>& piles, int k) {
int i, j, a, b;
j = 0;
for(i=0; i<piles.size(); ++i) {
if(piles[i] % k == 0) {
j = j + piles[i] / k;
}
else {
j = j + piles[i] / k + 1;
}
}
return j;
}
int bsearch(vector<int>& piles, int l, int r, int h) {
int i, j, k, mid;
mid = (l + r) / 2;
j = gethours(piles, mid);
if(j < h) {
if(l >= mid-1) return l;
return bsearch(piles, l, mid-1, h);
}
if(j > h) {
if(r <= mid+1) return r;
return bsearch(piles, mid+1, r, h);
}
return mid;
}
int minEatingSpeed(vector<int>& piles, int H) {
int i, j, k, s, l;
s = 1;
l = 0;
for(i=0; i<piles.size(); ++i) {
piles[i] > l ? l = piles[i] : l = l;
}
i = bsearch(piles, s, l, H);
j = gethours(piles, i);
if(j > H) {
while(gethours(piles, i) > H) {
i++;
}
return i;
}
while(i-1 >0 && gethours(piles, i-1) == H) {
i--;
}
return i;
}
};