二分查找 --(数值范围)--- 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

逻辑解释: 

'''

解释一下为什么这个为什么不用 left == right配合return mid 作为终止条件,而是用 left < right 作为终止条件
因为:
    1. left == right 时,mid = left = right,如果此时canFinish(mid)为False,那么会执行left = mid + 1,即left = right + 1,跳出循环
    2. left < right 时,mid = left + (right - left) // 2,如果此时canFinish(mid)为False,那么会执行left = mid + 1,即left = right,跳出循环
    3. 两种情况下,left == right,所以用 left < right 作为终止条件,可以避免多余的判断


'''

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值