二分查找算法的应用(循环条件和搜索区间如何确定)

二分查找算法相关的题最重要的就是如何确定循环条件搜索区间这两个细节:1. while循环的条件中left<=rightleft<right的确定;
2. 二分初始区间上界是nums.length-1还是nums.length

选取三种典型的题型分别进行分析:

1. 寻找一个数(基本的二分查找)

public int binarySearch(int[] nums,int target) {
        if(nums==null||nums.length==0){
            return -1;
        }
        int mid,left=0,right=nums.length-1;
        while(left<=right){
            mid=left+(right-left)/2;
            if(nums[mid]==target){
            	return mid;
            }else if(nums[mid]>nums[right]){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return -1;
}
  • 注意: 这里while循环条件为left<=right,二分初始区间上界rightnums.length-1
    • 因为区间[0,nums.length-1]能覆盖到所有可能返回的结果target要么存在于这个区间,要么不存在返回-1。所以上界rightnums.length-1
    • while循环条件为left<=right, 因为查找范围是[left , right],循环终止的条件是left==right+1,写成区间形式为[right+1 , right],这时区间为空就退出循环,说明target不存在直接返回-1。
    • while循环条件也可为left<right,循环终止的条件是left==right,写成区间形式为[right , right],此时还有right这个值未进入循环内判断就退出了循环,因此最后返回值部分需要写成return nums[right]==target?left:-1

2. 寻找第一个大于target的元素位置

public int upper_bound(int[] nums,int target) {
        if(nums==null||nums.length==0){
            return -1;
        }
        int mid,left=0,right=nums.length;
        while(left<right){
            mid=left+(right-left)/2;
            if(nums[mid]>target){
                right=mid;
            }else{
                left=mid+1;
            }
        }
        return left;
}
  • 注意: 这里while循环条件为left<right,二分初始区间上界rightnums.length
    • 考虑到欲查询元素有可能比序列中的所有元素都要大,二分上界取nums.length,搜索区间为[0,nums.length],当返回值为nums.length时,说明查询元素比序列中的所有元素都要大。
    • while循环条件为left<right, 因为不需要判断查询元素本身是否存在,就算它不存在,返回的也是它应该在的位置,于是循环终止的条件是left==right,写成区间形式为[right , right]刚好能夹出唯一的位置。

3. 寻找旋转排序数组中的最小值(LeetCode 153)

 public int findMin(int[] nums) {
         if(nums==null||nums.length==0){
             return -1;
         }
         int mid,left=0,right=nums.length-1;
         while(left<right){
             mid=left+(right-left)/2;
             //左区间连续,最小值在右区间
             if(nums[mid]>nums[right]){
                 left=mid+1;
             }else{
                 right=mid;
             }
         }
         return nums[left];
    }
  • 注意: 这里while循环条件为left<right,二分初始区间上界rightnums.length-1
    • 因为区间[0,nums.length-1]能覆盖到所有可能返回的结果,这个区间一定能取到最小值。
    • while循环条件为left<right, 循环终止的条件是left==right,写成区间形式为[right , right]刚好能夹出唯一的位置。

总结:

  • while循环的条件中left<=rightleft<right的确定由问题本身决定,如果查询元素一定存在搜索范围内,选择left<right可以夹出唯一的位置;而left<=right能将搜索区间范围一步步缩小,一直到区间为空才会退出。
  • 二分初始区间应该覆盖到所有可能返回的结果。

参考资料: 二分查找算法详解_labuladong.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值