leetcode系列--875.爱吃香蕉的珂珂

leetcode系列–第875题.爱吃香蕉的珂珂

珂珂喜欢吃香蕉。这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 H 小时后回来。
珂珂可以决定她吃香蕉的速度 K (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 K 根。如果这堆香蕉少于 K 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。  
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 H 小时内吃掉所有香蕉的最小速度 K(K 为整数)。
输入: piles = [3,6,7,11], H = 8
输出: 4
// 先写一下关于这道题的吐槽吧
// 再没看这道题的题解之前,我根本看不懂这道题是在讲什么,他要问什么,我要回答什么
// 看完部分题解以后就更云里雾里了,我知道这是关于二分解法的一道题,
// 但是以上来就二分,对小白无疑是雪上加霜。
// 复制几个评论区的大神的。   吐槽。。。
// 你一小时吃9亿根香蕉试试?
// piles.length <= H <= 10^9 10^9小时 = 114155年。这保安离开这么久,应该是刷题去了吧?
// 吃那么多也不怕撑死
// 开始我以为珂珂是小孩,看了一半题目,觉得是个猩猩或猴子,做了题目发现,这...是只猪?emm......
// 测试用例是不是太过分了? 这么多香蕉放在一起, 都他妈发生核聚变了, 珂珂在造恒星吗
// 警卫离开10^9小时还能回来?没有人质疑过警卫的物种吗?
思路来源----> laputaz
题意分解
题目的意思是说:
珂珂要吃香蕉,面前摆了 n 堆,一堆一堆地吃;
珂珂 1 小时能吃 k 个;但如果一堆少于 k 个,那也得花一小时 (一小时到了,才吃下一堆)
如果 1 堆大于 k 个,那么超过 整除k 的部分也算 1 小时。
(例如,一堆 10 个,k=3 时,珂珂花 3 小时吃了 9 个,剩下的 1 个也算 1 小时,也就是总用时 4 小时)
问:只给 h 小时,珂珂要吃多慢(k 多小),才能充分占用这 h 小时。

思路
珂珂吃的速度和时间是此消彼长的关系,吃的速度越快,花的时间越少。吃的速度越慢,花的时间越多。
我们要让珂珂吃得够慢,又能吃完。
那我们从最最慢开始,让珂珂一小时只吃 1 个(k=1),看珂珂能否在 h 小时内吃完。
如果吃不完,就吃 2 个(k+1),重头吃一遍。
一直到找到 k。
说到这里,就可以写出推断的代码了。(那怎么判断吃不吃得完? 这么想:它就是一个函数,吃得完返回 true,吃不完返回 false,具体实现可以后面再做)
// 该方法是最初的思路,会超时
var minEatingSpeed = function (piles, h) {
    // 最小的速度, 假设这个 🐷 一小时就吃最小的一根
    let k = 1;
    let isEnd = true;
    while (isEnd) {
        // 可以吃完,返回 k
        if (canFinish(k, h, piles)) {
            return k
        }
        // 当不能吃完的时候,多吃一根再试试
        k ++
    }
    // 每小时吃 k 根, 有 piles 堆, 给了 h 小时
    function canFinish(k, h, piles) {
        let totalTime = 0;
        for (let i = 0; i < piles.length; i ++) {
            // 当香蕉少于 k 的时候,当成 1 小时算
            if (piles[i] < k) {
                totalTime += 1
            } else {
                totalTime += Math.ceil(piles[i] / k)
            }
            if (totalTime > h) {
                return false
            }
        }
        return true
    }   
}
/**
 * @param {number[]} piles
 * @param {number} h
 * @return {number}
 */
var minEatingSpeed = function (piles, h) {
  // 左闭右开 所以 小于
  let left = 1,
    right = Math.max.apply(null, piles); // 求最大值 

  while (left < right) {
    let mid = Math.floor((right - left) / 2) + left
    // 只要进入这里说明 midnum 肯定 大于等于 target
    if (canFinish(mid, h, piles)) {
      right = mid
    } else {
      left = mid + 1
    }
  }
  return left

  // 每小时吃 k 根, 有 piles 堆, 给了 h 小时
  function canFinish(k, h, piles) {
    let totalTime = 0;
    for (let i = 0; i < piles.length; i++) {
      // 当香蕉少于 k 的时候,当成 1 小时算
      if (piles[i] <= k) {
        totalTime += 1
      } else {
        totalTime += Math.ceil(piles[i] / k)
      }

      if (totalTime > h) {
        return false
      }
    }
    return true
  }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值