题目描述
珂珂喜欢吃香蕉。这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 H 小时后回来。node
珂珂能够决定她吃香蕉的速度 K (单位:根/小时)。每一个小时,她将会选择一堆香蕉,从中吃掉 K 根。若是这堆香蕉少于 K 根,她将吃掉这堆的全部香蕉,而后这一小时内不会再吃更多的香蕉。python
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉全部的香蕉。c++
返回她能够在 H 小时内吃掉全部香蕉的最小速度 K(K 为整数)。web
示例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 是多少?svg
显然 K 越小,吃每堆香蕉所须要的时间就越长,总时间也就越长,那么天然而然能够想到二分答案 K 。学习
对于当前的 K ,咱们遍历数组,算出总时间,若是总时间大于 H ,那就说明 K 过小了,还得提速;若是总时间小于等于 H ,那就说明速度 K 还能够降一点,总时间可能不变(由于存在上取整),也可能变大。
这样最终的时间复杂度仅仅只有 ,其中 是数组中的最大值,也就是二分上界。但其实这里还能够优化一下二分的上下界,好比上界,最大其实就是数组中的最大元素大小, K 再大也没有意义了。
代码
c++
class Solution {public: int minEatingSpeed(vector<int>& 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 = 1 r = maxv while l < r: m = (r - l) // 2 + l cnt = 0 for p in piles: cnt += (p + m - 1) // m if cnt > H: l = m + 1 else: r = m return r
后记
注意上面的代码仍是有几个小细节的:
-
二分终止条件设置的是 l >= r ,因此 l 的更新必须是 l = m + 1 ,由于若是 l = r - 1 的话,m 会等于 l 。 -
为了防止整型溢出,计算 l 和 r 均值的时候不要写 (l + r) / 2 。 -
上取整简单写法就是 (p + m - 1) / m 。
做者简介:godweiyang,知乎同名,华东师范大学计算机系硕士在读,方向天然语言处理与深度学习。喜欢与人分享技术与知识,期待与你的进一步交流~
个人微信:weiyang792321264。有任何问题均可以在评论区留言,也欢迎加我微信深刻沟通~
本文分享自微信公众号 - 算法码上来(GodNLP)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。