有序数组二分查找模板

Posted 清水寺扫地僧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有序数组二分查找模板相关的知识,希望对你有一定的参考价值。


二分查找基础

二分本质上是对边界进行二分,将查找范围缩小为原先的一半。

查找有序数组中,会有如下相关的子问题可以运用二分进行解决:

  • ① 查找某一个数;
  • ② 最后一个小于目标值target的数;
  • ③ 最后一个小于等于目标值target的数;
  • ④ 第一个大于目标值target的数;
  • ⑤ 第一个大于等于目标值target的数;

采用二分查找,返回该数的索引,没有的话返回-10(non_exit) ;

int mid = (l + r) / 2int mid=l+(r-l)/2;的区别在于:
int mid = (l + r) / 2(l + r)可能出现整数溢出,这就导致计算结果不是正确的中位数。


① 查找某一个数

//二分查找某个数
int binarySearchOne(vector<int> vec, int target) {
	int l = 0, r = vec.size() - 1;
	while (l <= r) {
		int mid=l+(r-l)/2;
		if (vec[mid] == target)  //关键点
			return mid;
		if (vec[mid] > target) r = mid - 1;
		else l = mid + 1;
	}
	return non_exit;
}

② 最后的小于目标值target的数

//二分查找最后一个小于某个数
int binarySearchFirstLess(vector<int> vec, int target) {
	int l = 0, r = vec.size() - 1;
	while (l <= r) {
		int mid = l+(r-l)/2;
		//关键点,>=
		if (vec[mid] >= target)  r = mid - 1;
		else l = mid + 1;
	}
	//区分索引越界,即没找到
	if(r<0) return non_exit;
	return r;
}

③ 最后的小于等于目标值target的数,即右边界

//二分查找最后一个小于等于某个数,若相等则返回最右边的
int binarySearchFirstLessEqual(vector<int> vec, int target) {
	int l = 0, r = vec.size() - 1;
	while (l <= r) {
		int mid = l+(r-l)/2;
		 //关键点,>
		if (vec[mid] > target) r = mid - 1;
		else l = mid + 1;
	}
	//如果要找的是最后一个等于target的位置,则条件是 if(r<0 || vec[r]!=target)
	if (r < 0) return non_exit;
	return r;
}

分析

  • 对于题目②小于、题目③小于等于,代码不同的在于关键点处:
     题目②小于:则将大于等于分为一类;
     题目③小于等于:则将大于分为一类;
  • 最后返回,也即对应了题设中"最后的";

④ 第一个大于目标值target的数

//二分查找第一个大于某个数
int binarySearchFirstGreater(vector<int> vec, int target) {
	int l = 0, r = vec.size() - 1;
	while (l <= r){
		int mid = l+(r-l)/2;
		//关键点,<=
		if (vec[mid] <= target) l = mid + 1; 
		else r = mid - 1;
	}
	//区分索引越界,即没找到
	if (l >= vec.size()) return non_exit;
	return l;
}

⑤ 第一个大于等于目标值target的数,即左边界

//二分查找第一个大于等于某个数,若相等则返回最左边的
int binarySearchFirstGreaterEqual(vector<int> vec, int target) {
	int l = 0, r = vec.size() - 1;
	while (l <= r) {
		int mid = l+(r-l)/2;
		//关键点,<
		if (vec[mid] < target) l = mid + 1;
		else r = mid - 1;
	}
	//如果要找的是第一个等于target的位置,则条件是 if(l >= vec.size() || vec[l]!=target)
	if (l >= vec.size()) return non_exit;
	return l;
}

分析

  • 对于题目④大于、题目⑤大于等于,代码不同的在于关键点处:
     题目④大于:则将小于等于分为一类;
     题目⑤大于等于:则将小于分为一类;
  • 最后返回 l,也即对应了题设中"第一个";

以上是关于有序数组二分查找模板的主要内容,如果未能解决你的问题,请参考以下文章

[算法模板]二分查找

模板二分查找

二分算法(java超详细)

算法二分法 ② ( 排序数组中查找目标值 | 二分法的经典写法 | 在排序数组中查找元素的最后一个位置 | 二分法的通用模板 )

小航的算法日记数组

二分查找笔记