leetcode中“二分查找转化为判定问题”类题目

复杂的二分题目难点

第 410、1011、1482、1552、1760、2187、2226 题

1 根据题意确定二分查找左右边界

2 判定问题的方式:给定某一个二分索引,能否在某一限制值为x时,完成目标。

3 避免死循环: 决定是int m = (left+right+1)/2还是int m = (left+right)/2

4 返回结果的指针是left还是right

1 LC875. 爱吃香蕉的珂珂

class Solution {
    public int minEatingSpeed(int[] piles, int h) {
        int n=piles.length;
        int r=1;
        for(int p:piles){
            r=Math.max(r,p);
        }

        int l=1;
        while(l<=r){
            int m=(l+r)>>1;
            long cntH=getTime(piles,m);
            if(cntH<=h){
                r=m-1;
            }else{
                l=m+1;
            }
        }

        return l;
    }
	// 对应于解决问题的第二步:判定问题的方式
    public long getTime(int[] piles, int speed) {
        long res=0l;
        for(int t:piles){
            res+=Math.ceil(t*1.0/speed);        
        }
        return res;
    }

}

2 LC1011. 在 D 天内送达包裹的能力

class Solution {
    public int shipWithinDays(int[] weights, int days) {
        int n=weights.length;

        int l=Arrays.stream(weights).max().getAsInt(),r=Arrays.stream(weights).sum();
        while(l<=r){
            int m=(l+r)>>1;
            int d=getDay2(weights,m);
            // 当所需的天数大于规定天数时,说明运载能力需要增强
            if(d>days){
                l=m+1;
            }else{
                r=m-1;
            }
        }
        return l;
    }
    int getDay2(int[]weights,int m){
        int n=weights.length;

        int cur=0,need=1;

        for(int w:weights){
            if(cur+w>m){
                need++;
                cur=0;
            }
            cur+=w;
        }
        return need;
    }
    int getDay3(int[]weights,int m){
        int n=weights.length;
        int d=1;
        int t=m;
        for(int i=0;i<n;){
            t-=weights[i];
            if(t<0){
                d++;
                t=m;
            }else{
                i++;
            }
        }
        return d;
    }
}

3 LC1482. 制作 m 束花所需的最少天数

class Solution {
    public int minDays(int[] bloomDay, int m, int k) {
        int n=bloomDay.length;
        if((long)m*k>n){
            return -1;
        }
        int r=Arrays.stream(bloomDay).max().orElse(-1);
        int l=Arrays.stream(bloomDay).min().orElse(-1);

        while(l<=r){
            int mid=(l+r)>>1;

            boolean f=getB(bloomDay,m,k,mid);

            //能凑齐
            if(f){
                r=mid-1;
            }else{
                l=mid+1;
            }
        }
        return l;
    }

    boolean getB(int[]bloomDay, int m, int k, int day){
        
        int curK=k;
        for(int i=0;i<bloomDay.length;i++){
            if(day>=bloomDay[i]){
                curK--;
            }else{
                curK=k;
            }
            if(curK==0){
                curK=k;
                m--;
            }
            //凑齐了m束花,返回true
            if(m<=0){
                return true;
            }
        }

        return false;
    }
}

1 LC274. H 指数

 public int hIndex8(int[] citations) {
        int left=0,right=citations.length;
        int mid=0,cnt=0;
        while(left<right){
            // +1 防止死循环
            mid=(left+right+1)>>1;
            cnt=0;
            for(int i=0;i<citations.length;i++){
                if(citations[i]>=mid){
                    cnt++;
                }
            }
            if(cnt>=mid){
                // 要找的答案在 [mid,right] 区间内
                left=mid;
            }else{
                // 要找的答案在 [0,mid) 区间内
                right=mid-1;
            }
        }
        return left;
    }

    public int hIndex(int[] citations) {
        int n=citations.length;
        int ans=0;
        int maxCnt=0;
        int l=0,r=n;

        while(l<=r){
            int m=(l+r)>>1;

            int cnt=0;
            for(int i=0;i<n;i++){
                if(citations[i]>=m){
                    cnt++;
                }
            }

            if(cnt>=m){
                l=m+1;
            }else{
                r=m-1;
            }
        }
        return l-1;
    }

你可能感兴趣的:(数据结构,leetcode,算法,职场和发展)