java 二分搜索获得大于目标数的第一位_[算法总结]二分查找

关于二分查找算法,维基百科是这么说的:

二分查找算法,也称折半搜索算法。是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

几个关键点:

  • 前提是查找的序列是有序的。
  • 每次搜索过程与搜索区间的中点比较。
  • 搜索区间是如何变小的。(变化上界与下界)
  • 终止条件是搜索区间为空

先贴一下该算法的Java实现,最基础的。

要求:在有序序列中查找一个数,查找成功返回下标,查找失败返回-1

dcfbe4b286e0a2b319c636db2408df5a.png

两种模板,取决于搜索区间是[l, r]还是[l, r),相应的循环终止的条件也会发生改变。

public int binarySearch(int[] nums, int target) {
    int l=0, r=nums.length-1; 
    
    while(l<=r) { 
        int mid=l+(r-l)/2;
        
        if(nums[mid]==target) 
            return mid;
        else if(nums[mid]>target)   
            r=mid-1;    
        else if(nums[mid]<target)   
            l=mid+1;    
    }
    
    return -1;
}

public int binarySearch(int[] nums, int target) {
    int l=0, r=nums.length; =
    
    while(l<r) { =
        int mid=l+(r-l)/2;
        
        if(nums[mid]==target) 
            return mid;
        else if(nums[mid]>target)   
            r=mid;   
        else if(nums[mid]<target)   
            l=mid+1;    
    }
    
    return -1;
}

需要注意的是第二种模板由于其循环退出条件为搜索区间为空,左边界等于右边界,其实就相当于锁定了一个元素,我们只需要对这个锁定的元素进行判断就可以了,不用再分别判断lr。常用于查找一个数的左边界或者右边界。

常见的二分查找算法应用场景:

  • 查找一个数
  • 查找左侧边界
  • 查找右侧边界
    • 查找失败会有两种情况的返回值:target应该插入的位置或者-1

题目要求:查找元素第一次出现的位置,否则返回-1

即找到元素的左边界,关键点是1.采用左闭右开的搜索区间使得最后锁定一个元素的位置;2.因为搜索区间右边界无法取到,所以改变上界时取mid;3.当搜索到与目标值相等的元素后,先不返回,而是将搜索区间右边界继续缩小, 直到锁定到target第一次出现的位置。

public int binarySearch(int[] nums, int target) {
    int l=0, r=nums.length; 
    
    while(l<r) { 
        int mid=l+(r-l)/2;
        
        if(nums[mid]==target) 
            r=mid;
        else if(nums[mid]>target)   
            r=mid;    
        else if(nums[mid]<target)   
            l=mid+1;    
    }
    
    if(r==nums.length) return -1; 
    else return (nums[l]==target)? l : -1; 
/*  查找失败,要求返回插入位置
    if(r==nums.length) return nums.length; 
    else return l;
*/
}

题目要求:查找元素最后一次出现的位置,否则返回-1

需要注意与寻找左边界不同的是我们在这里返回的是l-1, 因为查找成功的最后一个判断语句是if(nums[mid]==target) l=mid+1; 即最后锁定的元素为查找成功的元素的后一位。

public int binarySearch(int[] nums, int target) {
    int l=0, r=nums.length; 
    
    while(l<r) { 
        int mid=l+(r-l)/2;
        
        if(nums[mid]==target) 
            l=mid+1;
        else if(nums[mid]>target)   
            r=mid;    
        else if(nums[mid]<target)   
            l=mid+1;    
    }
    
    if(l==0) return -1;
    else return (nums[l-1]==target)? l-1 : -1;
/*  查找失败,要求返回插入位置
    if(l==0) return 0; 
    else return (nums[l-1]==target)? l-1 : l;
*/
}

对于查找失败返回l的原因是二分查找不存在的元素,搜索区间会收敛到第一个大于目标的元素的下标。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值