Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一.题目
珂珂喜欢吃香蕉。这里有 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^4piles.length <= H <= 10^91 <= piles[i] <= 10^9
二、思路分析:
这道题目乍一看觉得不是什么二分搜索题目,但是我们直到一般的题目利用暴力解法往往会超出时间限制。所以这道题我根据laluladong大佬的思路确定了这道题可以使用二分搜索的思路进行求解,大佬提供的思路要求我们提供X,target以及f(X)。二分搜索问题实际上是找到一个我们需要的自变量X,根据题目,需要找到珂珂吃香蕉的速度,所以我们就确定X就是吃香蕉的速度,因为题目中说明珂珂喜欢慢慢吃,那么说明时间越慢越好,故target = H。我们还需要直到f(X)关于X的变化,已知X越大时间就越快,所以确定f(X)是单调递减的函数。一般来说,求最值的过程就是利用二分搜索查找所需要的值的最左还是最右值。
我们先进行初始化left和right变量,最小速度为1,最大速度就是所有堆中最多的香蕉数,所以我们可以得出需要是左侧target搜索还是右侧target搜索,由题目得知X越小越好,所以我们需要利用左侧target搜索的框架进行求解。
三、代码:
/**
* @param {number[]} piles
* @param {number} h
* @return {number}
*/
var minEatingSpeed = function(piles, h) {
let left = 1;
let right = Math.max(...piles);
const f = (piles,x) =>{
let hour = 0
for(const pile of piles){
hour += Math.ceil(pile/x)
}
return hour
}
while(left < right){
let mid = Math.floor(left + (right - left)/2)
if( f(piles,mid) == h){
right = mid
}else if(f(piles,mid) > h){
//需要让f(x)的返回值小一些,由于f(x)单调递减,所以需要自变量往右侧增加
left = mid + 1
}else if(f(piles,mid) < h){
//需要让f(x)的返回值大一些
right = mid
}
}
return left
};
四、总结:
我们在使用二分搜索求解问题的时候,一定要清楚在判断条件下
left和right怎么变化,如果f(x)针对于原数组的情况下,我们只需要按照基本的框架思路来写就可以,但是如果f(x)不是原数组而是关于x自变量变化的函数时,我们就需要直到f(x)是单调递增还是单调递减的函数,然后在判断条件的时候对left以及right的情况做出相应的更改。