题目描述:
珂珂喜欢吃香蕉。这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 H 小时后回来。
珂珂可以决定她吃香蕉的速度 K (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 K 根。如果这堆香蕉少于 K 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 H 小时内吃掉所有香蕉的最小速度 K(K 为整数)。
思路:
使用二分查找法 找出最小速度K 查找边界是 最小吃香蕉速度是1 ,即l=1 最大吃香蕉速度是 这堆香蕉中数量最大的那堆的数字 即r = max(piles).
import java.util.Arrays;
public class Solution {
public int minEatingSpeed(int[] piles, int h) {
// 最小吃香蕉速度是每小时吃1个 最大速度是每小时把数量最大的那堆吃完
int l = 1, r = Arrays.stream(piles).max().getAsInt();
// 设定边界条件 当 l == r的时候已经找到了解
while (l < r) {
// 取中间
int mid = l + (r-l)/2;
// 判断如果以当前速度吃完所有香蕉的时间 <= 规定时间 则向左找更小的速度
// 之所以是 <= 是因为当前的速度有可能就是最小的速度
if (eatingTimes(piles, mid) <= h) {
r = mid;
} else {
// 以当前速度吃完所有香蕉的时间 大于规定时间的时候 则需要更快的速度吃完 所以要向右找
// 这里一开始我也有些糊涂 一定要明确一点就是 这里边维护的数字是 速度 而不是 时间
l = mid + 1;
}
}
return l;
}
// 输出以当前速度吃完所有香蕉需要的时间
private int eatingTimes(int[] piles, int speed) {
int res = 0;
for(int pile : piles) {
// 先算能不能恰好吃完 吃不完的需要多花一个小时把剩的香蕉吃了
res += pile / speed + ((pile % speed > 0) ? 1 : 0);
}
return res;
}
}