875. 爱吃香蕉的珂珂(二分查找)

二分搜索只能用来查找元素吗?
参考下面这篇文章:二分搜索只能查找元素么?

当问题是在一个值有序的空间域中,获取一个满足条件的值,我们都可以考虑使用二分查找的方法,进行剪治去做,每次排除一半的搜索空间。

package com.heu.wsq.leetcode.binarysearch;

/**
 * 875. 爱吃香蕉的珂珂
 * @author wsq
 * @date 2021/4/26
 * 珂珂喜欢吃香蕉。这里有 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
 *
 * 链接:https://leetcode-cn.com/problems/koko-eating-bananas
 */
public class MinEatingSpeed {
    /**
     * 二分查找的场景题,不像是之前给了你一个有序数组,直接去寻找某个数,该题在二分查找之上增加了一层场景,
     * 让我们一眼看过去不是二分查找。
     * 下面的思想真是要去学习,把问题进行直观的分析,题目要求最小的速度完成,那么最小的速度可以是多少呢? 它的范围是多少?
     *
     * 
     * 那么我们先抛开二分查找技巧,想想如何暴力解决这个问题呢?
     * 首先,算法要求的是「H小时内吃完香蕉的最小速度」,我们不妨称为speed,请问speed最大可能为多少,最少可能为多少呢?
     * 显然最少为 1,最大为max(piles),因为一小时最多只能吃一堆香蕉。
     * 那么暴力解法就很简单了,只要从 1 开始穷举到max(piles),一旦发现发现某个值可以在H小时内吃完所有香蕉,这个值就是最小速度:
     * @param piles
     * @param h
     * @return
     */
    public int minEatingSpeed(int[] piles, int h) {
        if (piles == null || piles.length == 0){
            return 0;
        }
        if(piles.length > h){
            return -1;
        }
        int left = 1;
        int right = getMaxSpeed(piles);
        // 使用二分查找搜索满足条件的最小速度
        while(left <= right){
            int mid = (left + right) >> 1;

            boolean flag = canFinsh(piles, mid, h);
            if(flag){
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return left;
    }

    private int getMaxSpeed(int[] piles){
        int maxSpeed = 0;
        for(int s: piles){
            maxSpeed = Math.max(maxSpeed, s);
        }
        return maxSpeed;
    }

    private boolean canFinsh(int[] piles, int speed, int h){
        for(int pile: piles){
            int tmpH = getHour(pile, speed);
            if(tmpH > h){
                return false;
            }
            h -= tmpH;
        }
        return true;
    }

    private int getHour(int pile, int speed){
        return (pile + speed - 1) / speed;
    }
}

你可能感兴趣的:(LeeCode代码,java,leetcode,数据结构)