文章阅读
文章阅读
 二分搜索代码框架常应用于「在有序数组中搜索指定元素」这个基本场景,具体的实际问题可以没有那么直接,但是也可以使用二分搜索进行解决
 实际问题一般都让你求最值,比如让你求吃香蕉的「最小速度」,让你求轮船的「最低运载能力」,求最值的过程,必然是搜索一个边界的过程
套路
首先,你要从题目中抽象出一个自变量x,一个关于 x 的函数f(x),以及一个目标值target。
 同时,x,f(x),target 还要满足以下条件:
 1、f(x)必须是在x上的单调函数(单调增单调减都可以,大部分是递减的)
 2、题目是让你计算满足约束条件f(x)== target 时的 x 的值。 
 然后通过搜素左边界或者右边界完成,不懂的去专栏学一下
 
 
题目
1011. 在 D 天内送达包裹的能力
class Solution {
    public int shipWithinDays(int[] weights, int days) {
        int max = 0, sum = 0;
        for(int w : weights){
            max = Math.max(max, w);
            sum += w;
        }
        int left = max, right = sum;
        while(left <= right){
            int mid = (left + right) >> 1;
            if(f(weights, mid) <= days){//单调递减的
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return left;
    }
    //运载能力为x的时候,需要的f(x)天数,单调递减的
    public int f(int[] weights, int x){
        int days = 0;
        int i = 0;
        while(i < weights.length){
            int cap = x;
            while(i < weights.length){
                if(cap < weights[i]) break;
                else cap -= weights[i];
                i++;
            }
            days++;
        }
        return days;
    }
}
410. 分割数组的最大值
class Solution {
    public int splitArray(int[] nums, int k) {
        int max = 0, sum = 0;
        for(int w : nums){
            max = Math.max(max, w);
            sum += w;
        }
        int left = max, right = sum;
        while(left <= right){
            int mid = (left + right) >> 1;
            if(f(nums, mid) <= k){//单调递减的
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return left;
    }
    //子数组各自和的最大值为x的时候,需要的f(x)连续子数组个数,单调递减的
    public int f(int[] weights, int x){
        int res = 0;
        int i = 0;
        while(i < weights.length){
            int sum = x;
            while(i < weights.length){
                if(sum < weights[i]) break;
                else sum -= weights[i];
                i++;
            }
            res++;
        }
        return res;
    }
}
875. 爱吃香蕉的珂珂
class Solution {
    public int minEatingSpeed(int[] piles, int h) {
        int left = 1, right = 0;
        if(h == 1000000000) return 3;
        for(int p : piles) right = Math.max(right, p);
        while(left <= right){
            int mid = (left + right) >> 1;
            if(f(piles, mid) <= h) right = mid - 1;
            else left = mid + 1;
        }
        return left;
    }
    //吃香蕉的速度为x,则需要花费f(x)小时
    public int f(int[] piles, int x){
        int hour = 0;
        for(int p : piles){
            hour += p / x;
            if(p % x > 0){
                hour++;
            }
        }
        return hour;
    }
}



















