二分查找(数值范围)--- koko吃香蕉
来源:leedcode.875
题目描述:
珂珂喜欢吃香蕉。这里有 n 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 h 小时后回来。
珂珂可以决定她吃香蕉的速度 k (单位:根/小时)。
每个小时,她将会选择一堆香蕉,从中吃掉 k 根。
如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
求解她可以在 h 小时内吃掉所有香蕉的最小速度 k(k 为整数)。
思路:
- k 的最小值 1,最大值 max(piles)(一次性吃完最多的堆)
- 二分 k,检查是否能在 h 小时内完成
- 计算所需时间:time = sum(ceil(pile / mid))
”选速度k,判断时间;吃得慢就要加快速度“
理解点:
- 怎么用代码实现满足:”如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉“ ---- ceil() 向上取整
import math
def minEatingSpeed(piles, h):
left, right = 1, max(piles)
# 这部分用于解决 --> "如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉” -- ceil()
def canFinish(k):
return sum(math.ceil(pile / k) for pile in piles) <= h
while left < right:
mid = (left + right) // 2
if canFinish(mid):
right = mid # 继续尝试更小的 k
else: # 吃太慢了,提高速度
left = mid + 1 # 增大 k, 继续尝试
return left # 最小满足条件的 k
piles = [3, 6, 7, 11]
h = 8
# piles = [30,11,23,4,20]
# h = 5
# piles = [30,11,23,4,20]
# h = 6
print(minEatingSpeed(piles, h)) # 输出: 4
逻辑解释: