珂珂吃香蕉 java,每日算法系列【LeetCode 875】爱吃香蕉的珂珂

题目描述

珂珂喜欢吃香蕉。这里有 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 <= piles.length <= 10^4

piles.length <= H <= 10^9

1 <= piles[i] <= 10^9

题解

简单复述一下题意,就是有 N 堆香蕉,每堆有 piles[i] 个,现在要求一个整数速度 K ,吃一堆香蕉要的时间是 piles[i] / K (不是整数要上取整),问使得吃完所有香蕉所需总时间小于等于 H 的最小速度 K 是多少?

显然 K 越小,吃每堆香蕉所需要的时间就越长,总时间也就越长,那么自然而然可以想到二分答案 K 。

对于当前的 K ,我们遍历数组,算出总时间,如果总时间大于 H ,那就说明 K 太小了,还得提速;如果总时间小于等于 H ,那就说明速度 K 还可以降一点,总时间可能不变(因为存在上取整),也可能变大。

这样最终的时间复杂度仅仅只有

,其中

是数组中的最大值,也就是二分上界。但其实这里还可以优化一下二分的上下界,比如上界,最大其实就是数组中的最大元素大小, K 再大也没有意义了。

代码

c++

class Solution {public:int minEatingSpeed(vector& piles, int H){int maxv = *max_element(piles.begin(), piles.end());int n = piles.size();int l = 1, r = maxv;while (l < r) {int m = (r - l) / 2 + l;int cnt = 0;for (int i = 0; i < n; ++i) {cnt += (piles[i] + m - 1) / m;}if (cnt > H) l = m + 1;else r = m;}return r;}};

python

class Solution:def minEatingSpeed(self, piles: List[int], H: int) -> int:maxv = max(piles)l = 1r = maxvwhile l < r:m = (r - l) // 2 + lcnt = 0for p in piles:cnt += (p + m - 1) // mif cnt > H:l = m + 1else:r = mreturn r

后记

注意上面的代码还是有几个小细节的:

二分终止条件设置的是 l >= r ,所以 l 的更新必须是 l = m + 1 ,因为如果 l = r - 1 的话,m 会等于 l 。

为了防止整型溢出,计算 l 和 r 均值的时候不要写 (l + r) / 2 。

上取整简单写法就是 (p + m - 1) / m 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值