二分查找(划分时左右元素个数不相等)解析+代码

一:问题描述

当我们在用二分法查找元素的时候,我们往往特希望遇到是奇数个元素个数的数组,因为划分完左右两边的个数相等,所以在以前刚学二分法的时候就有这个疑问,当时就是模模糊糊过去了,再遇到其实还是会有疑问。现在实例验证遇见偶数个数数组元素个数时的二分法

二:思路+示例

目标:查询数组当中是否存在某个数,存在返回其下标,不存在返回-1;

思路:1.这是一个很典型的二分查找的例子,但关键的是我们要考虑其中的符号问题
2.也就是左闭右闭,左闭右开,左开右闭,这是二分法的重点,
3.我们一般使用的是左闭右闭,即[left,right],
举例如:
输入偶数个的数组array[7]: 我们想要查询29是否存在
1 5 9 11 23 29 31 50

 1>:我们在选取middle时  middle = 7/2 = 3 取下标为3的元素也就是112>:这时划分的数组左右长度不一样,跟我们常规的奇数个的时候不一样,这时我们对左右两边
	  		个数的考虑是多余的,因为我们每次都是将middle左边(右边)的所有元素均排除,跟个数
			  完全没有关系,
	  3>:回到上方的例子当中,我们比较2911的时候直接将左边的所有元素pass掉 
	  	下一次比较[middle+1,right]当中的元素,这里左右两边均取闭区间即左闭右闭	

三:上码

/**
  目标:查询数组当中是否存在某个数,存在返回其下标,不存在返回-1;
  
  思路:1.这是一个很典型的二分查找的例子,但关键的是我们要考虑其中的符号问题
  		2.也就是左闭右闭,左闭右开,左开右闭,这是二分法的重点,
		3.我们一般使用的是左闭右闭,即[left,right],
		举例如:
		输入偶数个的数组array[7]: 我们想要查询29是否存在 
			1 5 9 11 23 29 31 50    
		  
		  1>:我们在选取middle时  middle = 7/2 = 3 取下标为3的元素也就是11,
		  2>:这时划分的数组左右长度不一样,跟我们常规的奇数个的时候不一样,这时我们对左右两边
		  		个数的考虑是多余的,因为我们每次都是将middle左边(右边)的所有元素均排除,跟个数
				  完全没有关系,
		  3>:回到上方的例子当中,我们比较29和11的时候直接将左边的所有元素pass掉 
		  	下一次比较[middle+1,right]当中的元素,这里左右两边均取闭区间即左闭右闭	   
		    	

**/ 

#include<bits/stdc++.h>
using namespace std;

int find(int a[],int size,int target){
	
	int left = 0;
	int right = size - 1;//因为采用的左闭右闭,比如a[5],那么左右边界就是[0,4] 
	int mid;
	
	while(left <= right){ //当left == right时候 左闭右闭依然有效
	
		mid = left + (right - left)/2;//这里等价于  (right + left)/2
		
		if(a[mid] > target){
			right = mid - 1;
		}else if (a[mid] < target){
			left = mid + 1;
		}else{
			return mid;
		}
		
	}
	
	return -1;//没找到 
	
}


int main(){
	
	
	int a[10];
	int N,target;//N个数和要查询的数 
	
	cin >> N >> target;
	
	for(int i = 0; i < N; i++){
		cin >> a[i];
	} 
	
	int res = find(a,N,target);
	
	
	cout << res; 
	
} 



在这里插入图片描述

四:补充左闭右开

1:左闭右开[left,right)

即相应的while条件中(left < right) 而当a[mid] > target;时候,对应的 right = mid;

上码:

int search(int nums[], int size, int target)
{
	int left = 0;
	int right = size; //定义target在左闭右开的区间里,即[left, right)
	while (left < right) {	//因为left = right的时候,在[left, right)区间上无意义
		int middle = left + ((right - left) / 2);
		if (nums[middle] > target) {
			right = middle; //target 在左区间,在[left, middle)中 
		} else if (nums[middle] < target) {
			left = middle + 1;
		} else {
			return middle;
		}
	} 
    // 没找到就返回-1
	return -1;
}

参考自

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天向上的菜鸡杰!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值