编程之美之二分查找总结

二分查找原理很简单,但是边界条件容易出错,出现死循环等,要想彻底分清楚,应该要理解透彻,大家可以用先思考,然后用例子来验证,下面是我的思路,如果有错误,请指正。我们先看变形一:如果有很多待查找的数字,找出最大的,所以最大的一定是在最右边,为了能够把左右两个数进行对比,循环结束的时候,左右指针对应的数要相隔1,所以循环结束的条件left < right -1;要想保留最大下标,当data[mid] == value时,不能结束,因为data[mid+1]也可能等于value,所以要继续遍历,这时让left = mid,不能让right=mid,因为mid右边可能还有等于value的值,所以小于和等于要合并。变形二类似。再看变形三:为了找data[i]<value的最大i,当data[i]==value时也不能结束,此时,由于i肯定是在等于value的那个下标的左边,所以当data[i]==value时,要把right = mid继续遍历,即把大于和等于合并,而此时和变形一不同的时,要找的是小于,而不是等于,所以当data[i]>=value时,结果肯定在i的左边,不可能包括i,所以right = mid -1而不是mid,变形四类似。

标准的二分查找一:

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left <= right)//注意2
	{
		int mid = left + ((right - left) >> 1);//注意3
		if(data[mid] < value)left = mid + 1;
		else if(data[mid] > value)right = mid - 1;//注意4
		else return mid;
	}
	return -1;
}

标准的二分查找二(不常用):

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size();//注意1
	while(left < right)//注意2
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] < value)left = mid + 1;
		else if(data[mid] > value)right = mid;//注意3
		else return mid;
	}
	return -1;
}

变形一:如果有多个满足条件,返回序号最大的

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left < right - 1)
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] <= value)left = mid;//注意2
		else right = mid;//注意3
	}
	if(data[right] == value)return right;
	if(data[left] == value)return left;
	return -1;
}

变形二:如果有多个满足条件,返回序号最小的

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left < right - 1)
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] >= value)right = mid;//注意2
		else left = mid;//注意3
	}
	if(data[left] == value)return left;
	if(data[right] == value)return right;
	return -1;
}

变形三:求最大的i,使得data[i] < value


                
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值