持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
前言
今天的题目为中等,一道二分查找的变种题目,使用二分查找的思维能够节省时间复杂度,快速的查找到我们需要的那个值。
每日一题
今天的题目是 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 <= 104
- piles.length <= h <= 109
- 1 <= piles[i] <= 109
题解
二分查找
题目比较简单,能够根据题意转化为二分查找的问题。
首先我们要确定,每小时都要吃香蕉,那么每小时吃的最少的根数就是 1 ,每次最多吃一堆香蕉,那么每小时吃的最多的就是香蕉里面最多的那一堆的数量,知道这两点,那么就能够知道最开始的吃的速度的最小值和最大值,并且根据这一点,我们就能够获取当前吃的速度的中位数,用它来判断当前的中位数是快了还是慢了。
因为题目需要我们求出在 h 小时内吃掉所有香蕉的最小速度 k。
设每一堆香蕉为 pile 个,那么吃掉每一堆所需要的时间就是 pile/k 向上取整,这样我们就能够求出在当前速度下吃掉所有香蕉所需要的时间,
那么我们就可以利用二分查找不断地缩小这个范围,知道最后求出这个刚好满足条件的速度 k。
function minEatingSpeed(piles: number[], h: number): number {
let left = 1, right = Math.max(...piles)
while (left < right) {
const mid = (left + right) >> 1
if (getTime(mid, piles) <= h) {
right = mid
} else {
left = mid + 1
}
}
return left
};
function getTime(k:number, piles: number[]):number{
let s = 0
for(const pile of piles) {
s += Math.ceil(pile / k)
}
return s
}