【LeetCode 875】爱吃香蕉的珂珂

题目描述

原题链接: LeetCode.875 爱吃香蕉的珂珂

解题思路

  • 如果当前堆剩余香蕉数量小于每小时吃的数量, 吃完当前堆就会休息不会去吃下一堆的香蕉, 所以吃完一堆所需时间就是堆的香蕉数量除以速度的向上取整值:piles[i]/speed
  • 首先确定答案所处的范围, 速度最小值可以是1, 最大值很明显没必要超过所有堆中香蕉数量的最大值;
  • 如果假定的速度speed能在不超过指定H小时内吃完所有香蕉, 任意大于speed的速度也肯定可以在H小时内吃完, 否则就该尝试更小的speed能否在指定时间内吃完;
  • 二分判断函数逻辑就是给定speed能否在不超过H小时内吃完所有香蕉;
  • 在给定范围内不断二分尝试, 找到最小符合需求的速度即可;
  • 时间复杂度很明显就是O(nlogMAX);
  • 对于二分范围, 可以粗略定一个较大的, 对复杂度不会有多大影响, 追求极致性能的可以再细致的缩小边界, 但是务必注意不要遗漏正确的答案区域导致出错;

解题代码

  • 朴素二分法代码:

      /**
       * 典型二分查找的题目
       * 执行用时: 6 ms , 在所有 Java 提交中击败了 99.30% 的用户
       * 内存消耗: 14.75 MB , 在所有 Java 提交中击败了 14.75% 的用户
       */
      public int minEatingSpeed(int[] piles, int h) {
          int left = 1, right = 0;
          for (int p : piles) {
              right = Math.max(p, right);
          }
          int ans = left;
          while (left <= right) {
              int mid = left + ((right - left) >> 1);
              if (eatAllWithinH(piles, h, mid)) {
                  ans = mid;
                  right = mid - 1;
              }
              else {
                  left = mid + 1;
              }
          }
          return ans;
      }
    
      private boolean eatAllWithinH(int[] piles, int h, int speed) {
          int cnt = 0;
          for (int p : piles) {
              // 吃掉一堆的小时数是piles[i]/speed向上取整的值
              cnt += (p - 1) / speed + 1;
              if (cnt > h) {
                  return false;
              }
          }
          return true;
      }
    
  • 更细致的二分范围代码:

      /**
       * 对复杂度没影响, 但是能稍微优化些的二分范围值
       * 执行用时: 1 ms , 在所有 Java 提交中击败了 99.69% 的用户
       * 内存消耗: 43.99 MB , 在所有 Java 提交中击败了 64.63% 的用户
       */
      public int minEatingSpeed(int[] piles, int h) {
          long sum = 0;
          for (int p : piles) {
              sum += p;
          }
          int left = (int) ((sum - 1) / h) + 1;
          int right = (int) (sum / (h - piles.length + 1)) + 1;
          int ans = left;
          while (left <= right) {
              int mid = left + ((right - left) >> 1);
              if (eatAllWithinH(piles, h, mid)) {
                  ans = mid;
                  right = mid - 1;
              }
              else {
                  left = mid + 1;
              }
          }
          return ans;
      }
    

posted on   真不如烂笔头  阅读(36)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示