首页 > 代码库 > 编程之美之二分查找总结

编程之美之二分查找总结

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

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-1;//注意3
	}
	if(data[right] < value)return right;
	if(data[left] < value)return left;
	return -1;
}


变形四:求最小的i,使得data[i] > value

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 + 1;//注意3
	}
	if(data[left] > value)return left;
	if(data[right] > value)return right;
	return -1;
}