二分查找闭区间(l<=r)类总结

最近做题遇到二分查找,对于区间的取值以及最后的结果模棱两可。对于(l<=r)这种闭区间的。取值的范围是[left,right],一定要保证每次循环结束后left+1或者right-1,结束的状态left>right,left在右边,right在左边,目标值下标确定是left。
在这里插入图片描述

278. 第一个错误的版本

本题相当于一个数组,左边都是false,某一个位置开始都是true。需要找到第一个出现的true。使用闭区间计算,最后的时候left>right,所以left就是第一个出现的true,right是最后一个false,直接返回left即可。

/* The isBadVersion API is defined in the parent class VersionControl.
      boolean isBadVersion(int version); */

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int l=1;
        int r=n;
        while(l<=r){
            int mid=l+(r-l)/2;
            if(isBadVersion(mid))
            r=mid-1;
            else
            l=mid+1;
        }
        return l;
    }
}

剑指 Offer 53 - II. 0~n-1中缺失的数字

与上题分析相同,左边都是满足+1递增的,找到第一个不满足的,也就是返回右边部分的第一个,直接返回left就可以

class Solution {
    public int missingNumber(int[] nums) {
        int j=nums.length-1;
        int i=0;
        while(i<=j){
            int mid=i+(j-i)/2;
            if(mid==nums[mid])
            i=mid+1;
            else 
            j=mid-1;
        }
        return i;
    }
}

69. x 的平方根

左边的数都是满足mid* mid<=x,右边从某个位置开始mid*mid>x,所以需要找到左边的最后一个数,实际上就是返回right的下标,但本题考虑int溢出问题,所以使用ans记录左边的最后一个下标,来代替返回high的位置。

class Solution {
    public int mySqrt(int x) {
        if(x==1)
        return 1;
        int low=0;
        int high=x;
        int mid=0;
        int ans=0;//记录最后一个满足的下标
        while(low<=high){
            mid=low+((high-low)>>1);
            if((long)mid*mid<=x){
             ans=mid;
             low=mid+1;//low最后是不满足题意的,ans是最后一个满足的
            }
            else 
            high=mid-1;
        }
        return ans;
    }
}

35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。左边的判断条件是(nums[mid]<target),所以left最后是大于等于目标值的第一个。而right是小于目标值的最后一个。返回left即可。

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n=nums.length;
        if(n==0||target<nums[0])
        return 0;
        int l=0;
        int r=n-1;
        while(l<=r){
            int mid=(r-l)/2+l;
            if(nums[mid]>=target){
            r=mid-1;
            }
            if(nums[mid]<target)
            l=mid+1;
        }
        return l;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值