875. 爱吃香蕉的珂珂

163 阅读3分钟

[875. 爱吃香蕉的珂珂]

「这是我参与2022首次更文挑战的第2天,活动详情查看: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

思路

按照题目要求,这道题求的是在 H 小时内吃掉所有香蕉的最小速度 K(K 为整数)。按照题目要求,需要的结果是能在 H 小时内将香蕉吃完的最小速度。求的是速度,即最在要求的时间内,速度最小。这里涉及到两个变量,H小时和吃的速度,题目已经给出了H小时,那么可以从速度开始思考。

那么,可以先想出在忽略小时H的情况下考虑速度的范围。那么首先最小速度应该是1,这样珂珂才有可能吃到香蕉,此时的小时数为最大值。最大速度应为香蕉中最大的那一堆,这样就可以一小时吃一堆,再大没有必要,此时的小时数为最小值。可以发现运载量都可以对应到一个天数。

这道题与昨天:“1011. 在 D 天内送达包裹的能力”十分相似。也可以使用二分查找,计算当前速度所需要的最小小时数,不断的逼近H。得解。

代码实现

使用二分查找,有以下三个步骤: 做法步骤:

  1. 分析题意,确定区间
  2. 根据题意写判断函数
  3. 进行二分查找

具体到这道题,按照上述思路,区间为1到香蕉堆里的最大值,判断函数为,在给定的速度和天数,能否吃完这一堆香蕉,之后进行二分查找,需要注意到while循环的退出条件,是否要+1,需要返回哪一个值等等问题。而与昨天的题对比,发现最大的不同可能只是判断函数。

 class Solution {
 private:
     bool CantEat(vector<int>& piles,int h,int k){
         int time=0;
         for(int banana:piles)
             time+=(banana-1)/k+1;    //计算出吃完当前堆的天数
         return time>h;
     }
 public:
     int minEatingSpeed(vector<int>& piles, int h) {
         int left=1,right=*max_element(piles.begin(), piles.end());   //确定上下界
         while(left<right){ //二分查找,找符合条件的最小值
             int mid=left+(right-left)/2;
             if(CantEat(piles,h,mid))   //吃不完,移动左,使变大
               left=mid+1;
             else                 //吃得完,移动右,使变小,逼近最小
               right=mid;
         }
         return left;   //循环结束时,执行的是left=middle+1,处于有效区间内。 
     }
 };

总结

通过今天和昨天的两篇文章,可以得出使用二分查找的一般步骤,就是分析题意,确定区间,根据题意写判断函数,进行二分查找。同时也可以得出二分查找的一般代码框架。大概是有一个判断函数,主函数中,声明左右区间,在while()循环中使用判断函数进行查找。