猴子吃桃:玩转二分思维

前言

在计算机编程领域,算法是解决问题的有效途径之一。而算法题则是考察程序员解决问题能力的重要手段之一。在这篇文章中,我们将通过一个经典的算法题目——猴子吃桃,来探讨算法思维的重要性以及解题的方法。

题目描述

孙悟空喜欢吃蟠桃,一天他乘守卫蟠桃园的天兵天将离开了而偷偷的来到王母娘娘的蟠桃园偷吃蟠桃。

已知蟠桃园有 N 棵蟠桃树,第 i 棵蟠桃树上有 N[i](大于 0)个蟠桃,天兵天将将在 H(不小于蟠桃树棵数)小时后回来。

孙悟空可以决定他吃蟠桃的速度 K(单位:个/小时),每个小时他会选择一颗蟠桃树,从中吃掉 K 个蟠桃,如果这棵树上的蟠桃数小于 K,他将吃掉这棵树上所有蟠桃,然后这一小时内不再吃其余蟠桃树上的蟠桃。

孙悟空喜欢慢慢吃,但仍想在天兵天将回来前将所有蟠桃吃完。

求孙悟空可以在 H 小时内吃掉所有蟠桃的最小速度 K(K 为整数)。

输入描述:

从标准输入中读取一行数字,前面数字表示每棵数上蟠桃个数,最后的数字表示天兵天将将离开的时间。

输出描述:

吃掉所有蟠桃的 最小速度 K(K 为整数)或 输入异常时输出 -1。

示例 1:

输入:

3 11 6 7 
8

输出:

4

说明:
天兵天将8个小时后回来,孙悟空吃掉所有蟠桃的最小速度4。

第1小时全部吃完第1棵树,吃3个,
第2小时吃4个,第2棵树剩7个,
第3小时吃4个,第2棵树剩3个,
第4小时吃3个,第2棵树吃完,
第5小时吃4个,第3棵树剩2个,
第6小时吃2个,第3棵树吃完,
第7小时吃4个,第4棵树剩3个,
第8小时吃3个,第4棵树吃完。


题目分析

这道题目是一个典型的搜索问题,需要我们找到一个最小的速度 K,使得孙悟空能在规定的时间内吃掉所有的蟠桃。

原题为:875. 爱吃香蕉的珂珂
https://leetcode.cn/problems/koko-eating-bananas/description/

解题思路

我们可以通过二分查找的方式来确定孙悟空吃蟠桃的速度 K。首先,我们需要确定二分查找的搜索范围,最小速度 K 的下界是 1,最大速度 K 的上界是所有蟠桃中的最大数量。

对于每一个速度 K,我们可以计算出孙悟空吃完所有蟠桃需要的时间,然后将这个时间与规定的时间 H 进行比较。

  • 如果孙悟空需要的时间小于等于规定的时间,说明速度 K 可行,我们就可以将速度 K 的上界缩小;
  • 如果孙悟空需要的时间大于规定的时间,说明速度 K 不够快,我们就需要将速度 K 的下界增大。

代码实现

from typing import List
from loguru import logger


class Solution:
    def min_eating_speed(self, coiled_peach: List[int], h: int) -> int:
        if not coiled_peach or h < len(coiled_peach):
            return -1

        # 二分查找速度 K 的上界和下界
        left, right = 1, max(coiled_peach)
        while left < right:
            mid = (left + right) // 2
            if self.can_eat_all(coiled_peach, h, mid):
                right = mid
            else:
                left = mid + 1
        return left

    def can_eat_all(self, coiled_peach, h, K):
        """
        判断孙悟空在给定速度 K 的情况下是否能在规定时间 h 内吃完所有的蟠桃。

        Args:
            coiled_peach (list): 每棵蟠桃树上的蟠桃数量列表。
            h (int): 天兵天将回来的时间。
            K (int): 孙悟空吃蟠桃的速度。

        Returns:
            bool: 如果能在规定时间内吃完所有蟠桃,则返回 True,否则返回 False。
        """
        total_time = sum((num + K - 1) // K for num in coiled_peach)  # 记录吃完所有桃树的时间
        return total_time <= h


if __name__ == "__main__":
    s_instance = Solution()

    min_speed = s_instance.min_eating_speed(coiled_peach=[3, 11, 6, 7], h=8)
    logger.info(f"get min speed: {min_speed}")

    min_speed = s_instance.min_eating_speed(coiled_peach=[2, 3, 4, 5], h=3)
    logger.info(f"get min speed: {min_speed}")

    min_speed = s_instance.min_eating_speed(coiled_peach=[2, 3, 4, 5], h=4)
    logger.info(f"get min speed: {min_speed}")

    min_speed = s_instance.min_eating_speed(coiled_peach=[30, 11, 23, 4, 20], h=6)
    logger.info(f"get min speed: {min_speed}")

    min_speed = s_instance.min_eating_speed(coiled_peach=[30, 11, 23, 4, 20], h=5)
    logger.info(f"get min speed: {min_speed}")

输出结果为:

总结

通过二分查找的方法,我们可以高效地找到孙悟空吃蟠桃的最小速度 K。这种解题思路可以应用于类似的搜索问题,能够在保证时间效率的情况下得到正确的结果。

  • 21
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值