- 珂珂喜欢吃香蕉。这里有
n
堆香蕉,第i
堆中有piles[i]
根香蕉。警卫已经离开了,将在h
小时后回来。- 珂珂可以决定她吃香蕉的速度
k
(单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉k
根。如果这堆香蕉少于k
根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。- 珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
- 返回她可以在
h
小时内吃掉所有香蕉的最小速度k
(k
为整数)。
根据示例观察来看,吃香蕉越快耗时最短,而吃香蕉最快的则是香蕉堆中,最多香蕉的那一堆、
因为如果选择最多香蕉的那一堆一个小时吃完,那么其他的也能够一个小时吃完,所以最快的香蕉则是一小时吃完 拥有最多香蕉的那一堆。
于是,k最大值就是piles数组内的最大值,同时最大值也就等于了piles的长度。
而我们需要在h小时内吃完香蕉,所以k的最小值就是需要保证能够吃完所有香蕉的同时不超时且不能是最大值。
int minEatingSpeed(vector<int>& piles, int h) {
for(int k=1;k<=ranges::max(piles);k++)
{
long sum=0;
for(int p:piles)
{
sum += (p + k - 1) / k; //向上取整
}
if(sum<=h)
{
return k;
}
}
return piles.size();
}
};
但是,以上的方法会让我们的时间复杂度超时,因为是枚举法,于是我们使用二分查找方法。
这一题使用二分查找方法,是建立在我们已经观察到了一定会有一个数字既能小于最大堆的香蕉数,又能在规定的h小时内吃完所有的香蕉。
所以设立一个left = 1,一个right为最大香蕉数量,随后进行计算。
int minEatingSpeed(vector<int>& piles, int h)
{
//计算vector 类型的piles 内部的最大数
int maxPiles = *std::max_element(piles.begin(), piles.end());
int left = 1, right = maxPiles;
while (left < right)
{
int mid = left + (right - left) / 2;
//使用二分查找方式得出一个中间值,让中间值来充当每小时能够吃掉的香蕉数
int hours = 0;
for (int pile : piles)
{
hours += (pile + mid - 1) / mid; // 使用整数除法,并向上取整
}
if (hours <= h)
{
right = mid; // 尝试找到一个更小的速度
}
else
{
left = mid + 1; // 需要更快的速度
}
}
return left;
}