LeetCode 875 爱吃香蕉的珂珂
题目描述
题目给定一个数组,代表每一堆香蕉的个数,给定一个时间H
。要求在时间h
内,吃完所有香蕉的最小速度k/h
。其中注意:如果吃的速度大于香蕉个数,也是耗费1h,并且是一堆一堆的吃
解题思路
1、最小速度肯定是在时间
h
内,把所有香蕉吃完,即所有香蕉 / h (上取整)
,最大速度就是所有堆中最大的一堆(提示保证了h >= 堆数
)
2、我们用暴力遍历的想法来看,从最小速度k
开始,遍历一遍吃完所有堆所用时间t
,如果t > h
则代表我们的速度不满足题意,太慢了。
3、暴力的做法就是自增k
,每次k+=1
,再去重复 2 2 2 的遍历,求t
,直到t <= h
4、由于数据量数10^4^
,自增遍历的话,奖励TLE
。
5、所以我们在从最小速度到最大速度的自增
过程,就是为了找到那个合适的最小速度,我们记最终速度为k
,当我们的速度小于k
时,此时去遍历的时候算出来的t肯定大于h
,反之,速度大于k
时,t <= h
. 我们为了加快找到正确答案的速度,就需要向二分查找的方法上去想 (没想到刷题锻炼,俺也一样)
这里补充一下,上取整的方法:
对于上取整,两个整型的数据作除法,若整除,取商即可。若不能整除(有小数),应取商+1.
方法:直接按照上述的描述。
if(a % b == 0) return a / b; else return a / b + 1;
还有一种是数学推理出来:(a + b - 1)/ b;
这里放上之前我写过的一个二分的模板:二分模板,这个题目大家也可以练手
代码(c++)
class Solution {
public:
long calc(long a, int b)
{
if(a % b == 0)
return a / b;
else
return a / b + 1;
}
int minEatingSpeed(vector<int>& piles, int h) {
int len = piles.size();
long all = accumulate(piles.begin(), piles.end(), 0LL);
int low = calc(all, h), high = 0;
for(auto pile : piles)
high = max(high, pile);
while(low < high)
{
int mid = (high - low) / 2 + low;
long t = 0;
for(int i = 0; i < len; i++)
{
t += calc(piles[i], mid);
}
if(t <= h)
{
high = mid;
}
else
{
low = mid + 1;
}
}
return low;
}
};