再学二分查找

四种二分查找代表各自的意义

①区间是左闭右闭,依靠mid来查找目标

	// 区间是闭区间[left,right]
	public int search(int[] nums, int target) {
		int left = 0;
		int right = nums.length - 1;
		while (left <= right) { //重点
			int mid = left + (right - left) / 2;
			if (nums[mid] == target) return mid;
			if (nums[mid] < target) {
				left = mid + 1;
			} else {
				right = mid - 1;//重点
			}
		}
		return -1;
	}

②区间是左闭右开,依靠mid来查找目标

    // 区间是左闭右开[left,right)
	public int search(int[] nums, int target) {
		int left = 0;
		int right = nums.length;
		while (left < right) {
			int mid = left + (right - left) / 2;
			if (nums[mid] == target) return mid;
			if (nums[mid] < target) {
				left = mid + 1;
			} else {
				right = mid;
			}
		}
		return -1;
	}

③区间是左闭右开,不依靠mid,当二分到区间就有一个值时,该值只有两种结果,是目标返回left,或者不是目标返回-1,

    //不通过mid查找元素,但是要保证区间长度大于1,
    //即必须保证最后一次循环即只有两个元素时不会出现问题
    //左闭右开时,mid靠右
    //什么是mid靠右,就是只有两个元素时指向右边元素.假设两个元素为(1,5),下标mid=1=0+(2-0)/2,
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length;
        while(left + 1 < right){
            int mid = left + (right-left)/2;//mid靠右
            if(target >= nums[mid]){
             //①是因为nums[mid]可能=target,所以不能mid+1;
            //②又因为只有两个元素时mid靠右,即mid比left大,因此left往前移了一步.不会导致死循环
                left = mid ; 
            }else{
           		right = mid ;//right满足不在旧区间	
            }  
        }
        if(nums[left]==target) return left;
        else return -1;
    }

④区间是左闭右闭,不依靠mid,当二分到区间就有一个值时,该值只有两种结果,是目标返回right,或者不是目标返回-1,

    //不通过mid查找元素,但是要保证区间长度大于1,即必须保证退出循环的时候区间长度=1
   public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        while(left < right){
            int mid = left + (right-left)/2;//mid靠左,因为靠左,所以后面也需要变化
            //1.因为天生靠左,所以在只有两个元素时,必须要将target=nums[mid]放在target<=nums[mid]上,这样right指向元素才有可能=target,这样才能避免死循环
            if( target <= nums[mid]){
                right = mid ;//确保在target=nums[mid]不后退;在target<nums[mid],后退一步(因为mid天生靠左)  
            }else{
             	left = mid+1 ;//确保left进了一步,且不在旧区间
            }  
        }
        if(nums[right]==target) return right;
        else return -1;
    }

总结上面四种方式,①②比较好理解,只要能理解right是否在当前区间就能把边界值搞定。
③④之所以要考虑mid靠左靠右和考虑<=还是>=是因为需要解决死循环的问题,因为left或者right=mid,有可能会导致死循环,但是如果mid靠左,target<=nums[mid] (right=mid),或者mid靠右,target>=nums[mid] (left=mid)就可以避免死循环.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值