二分法

二分法

leetcode 410、875、774、1482、1011
一、能使用二分法的题所具有的共同特点:
(1)一般不能调整数组中元素的位置
(2)一般有一个累加的过程求最值
leetcode875

public int minEatingSpeed(int[] piles, int H) {
        int left = 1;
        int right = Integer.MIN_VALUE;
        for(int i=0;i<piles.length;i++){
            //left = Math.min(left,piles[i]);
            right = Math.max(right,piles[i]);
        }
        if(H == piles.length){
            return right;
        }
        if(piles.length == 1){
            return (piles[0]%H)==0 ? (piles[0]/H):(piles[0]/H+1);
        }
        while(left < right){
            int mid = left+(right-left)/2;
            if(mid == 0){
                mid = 1;
            }
            int h = 0;
            //特别注意这里h每次的取值
            for(int i=0;i<piles.length;i++){
                h+=(piles[i]%mid == 0)?(piles[i]/mid):(piles[i]/mid+1);
            }
            if(h>H){
                left = mid+1;
            }else{
                right = mid;
            }
        }
        return left;
    }

二、本题使用了基于贪心的二分算法。注意要点:

  1. 首先是确定left和right的值,确定left的取值很重要,在一些题里left的值是取数组的最小值,比如说这个花束

    再比如
    在这里插入图片描述
    这个题的left取值就必须要大于等于最重的包裹重量。珂珂爱吃香蕉这道题的left取值又是从1开始取。因此在确定left的取值时一定要特殊问题具体分析,从而确定left的值。right的值一般是数组中的最大值或者数组所有值的和。
  2. 注意在对left和right进行重新赋值时,left=mid+1,right=mid。为什么呢?
    (1)先猜一个mid值,然后遍历数组划分,使每个子数组和都最接近mid(贪心地逼近mid),这样我得到的子数组数一定最少;
    (2)如果即使这样子数组数量仍旧多于m个,那么明显说明我mid猜小了,因此 left = mid + 1;
    (3)而如果得到的子数组数量小于等于m个,那么我可能会想,mid是不是有可能更小?值得一试。因此 right = mid;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值