题目描述
珂珂喜欢吃香蕉。这里有 n 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 h 小时后回来。
珂珂可以决定她吃香蕉的速度 k (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 k 根。如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 h 小时内吃掉所有香蕉的最小速度 k(k 为整数)。
示例1:
输入: piles = [3,6,7,11], h = 8
输出: 4
示例2:
输入: piles = [30,11,23,4,20], h = 5
输出: 30
示例3:
输入: piles = [30,11,23,4,20], h = 6
输出: 23
提示
- 1 < = p i l e s . l e n g t h < = 1 0 4 1 <= piles.length <= 10^4 1<=piles.length<=104
- p i l e s . l e n g t h < = h < = 1 0 9 piles.length <= h <= 10^9 piles.length<=h<=109
- 1 < = p i l e s [ i ] < = 1 0 9 1 <= piles[i] <= 10^9 1<=piles[i]<=109
方法:二分查找
解题思路
当珂珂吃香蕉的速度越快,则总耗时越少;当珂珂吃香蕉的速度越慢,则总耗时越多。由此,说明了本题具有单调性,因此可以利用二分查找来解题。
因此,题目要求在 h 小时内吃掉所有香蕉的最小速度 k,根据上面分析所得,可转化为求在总耗时不超过 h 小时的情况下,珂珂吃香蕉的最大速度。
因为珂珂每 1 h 会选择某一堆香蕉吃,所以 k 可以取值的左边界为 1,而右边界为 1 0 9 10^9 109。
如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。 所以,我们在检查当前 mid 是否符合条件时,计算珂珂吃某一堆香蕉的用时,需要上取整。
假定某一堆香蕉根数为
p
i
l
e
s
[
i
]
piles[i]
piles[i],以每 1 h 吃 k 根香蕉的速度计算,珂珂吃某一堆香蕉的用时为
⌈
p
i
l
e
s
[
i
]
k
⌉
,等价于
⌊
p
i
l
e
s
[
i
]
+
k
−
1
k
⌋
。
\lceil\frac{piles[i]}{k}\rceil,等价于 \lfloor\frac{piles[i] + k - 1}{k}\rfloor。
⌈kpiles[i]⌉,等价于⌊kpiles[i]+k−1⌋。
代码
class Solution {
public:
int check(vector<int>& piles, int k, int h) {
int sum = 0;
for(int i = 0; i < piles.size(); i++)
sum += (piles[i] + k - 1) / k;
return sum <= h;
}
int minEatingSpeed(vector<int>& piles, int h) {
int l = 1, r = 1e9, mid;
while(l < r)
{
mid = (l + r) >> 1;
if(check(piles, mid, h))
r = mid;
else
l = mid + 1;
}
return l;
}
};
复杂度分析
- 时间复杂度:
O
(
n
l
o
g
m
)
O(nlogm)
O(nlogm)。
其中 n 是数组 piles \textit{piles} piles 的长度,m 是数组 piles \textit{piles} piles 中的最大值。二分查找需要执行 O ( log m ) O(\log m) O(logm) 轮,每一轮二分查找需要 O ( n ) O(n) O(n) 的时间,因此总时间复杂度是 O ( n log m ) O(n \log m) O(nlogm)。 - 空间复杂度: O ( 1 ) O(1) O(1)。