有序数组二分查找模板


二分查找基础

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

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

  • ① 查找某一个数;
  • ② 最后一个小于目标值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,也即对应了题设中"第一个";
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值