整数二分查找的实现

        这是C++算法基础-基础算法专栏的第五篇文章,专栏详情请见此处


引入

        在一个有序数组中,如果我们想查找某一元素,朴素做法就是从前往后枚举,时间复杂度会达到O\left ( n \right )。但是因为此数组是有序的,所以就可以通过这个性质,使用二分查找实现,可以使时间复杂度降到O\left ( log_{2}n \right )

        下面我们就来讲整数二分查找的实现。

定义

        二分查找(binary search),也称折半搜索(half-interval search)、对数搜索(logarithmic search),是用来在一个有序数组中查找某一元素的算法。

过程

        整数二分查找的思路是这样的:假设目标值在闭区间\left [ l,r \right ]中, 每次将区间长度缩小一半,当l=r时,我们就找到了目标值。

        以在一个升序数组中查找一个数为例。

        它每次考察数组当前部分的中间元素,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果中间元素大于所查找的值同理,只需到左侧查找。

        我们通常想到二分查找就会想到单调性,认为二分查找只能用于具有单调性的题目。其实不然,只要一个题目具有二段性,二分查找就有用武之地。

Q:什么是单调性呢?

A:单调性通俗点说,就是元素有序,即一个升序或降序的数组。

Q:那什么又是二段性呢?

A:二段性是指对某一范围内的数据,存在一个临界点,使得临界点某一侧的所有数据都满足某一性质,另一侧的所有数据都不满足这一性质,就称这一范围内的数据具有二段性。

        我们可以从中看出,二分查找的本质不在于单调性,而是二段性!

        其实,整数二分查找比浮点数二分查找要复杂得多,浮点数二分查找无需考虑边界,而整数二分查找在代码实现上还要判断加1减1。

        所以,整数二分查找如果写之前不考虑好想要查找的是什么,十有八九会是死循环或者查找错误,就算侥幸写对了也只是运气好而已!

性质

        时间复杂度

        二分查找的平均与坏时间复杂度均为O\left ( log_{2}n \right ),最优时间复杂度为O\left ( 1 \right )

        空间复杂度

        二分查找的空间复杂度为O\left ( 1 \right )(迭代版本)。

代码

        下面给出两种整数二分查找函数的实现:

bool check(int x){

}

int bsearch_1(int l,int r){
	while(l<r){
		int mid=l+r>>1;
		if(check(mid))
			r=mid;
		else
			l=mid+1;
	}
	return l;
}

int bsearch_2(int l,int r){
	while(l<r){
		int mid=l+r+1>>1;
		if(check(mid))
			l=mid;
		else
			r=mid-1;
	}
	return l;
}
        代码解释

        check()函数的作用是检查x是否满足某种性质;bsearch_1()函数的作用是区间\left [ l,r \right ]被划分成\left [ l,mid \right ]\left [ mid+1,r \right ]时使用(即查找左边界);bsearch_2()函数的作用是区间\left [ l,r \right ]被划分成\left [ l,mid-1 \right ]\left [ mid,r \right ]时使用(即查找右边界)。

        两种整数二分查找函数的区别

        这两种整数二分查找函数有什么区别呢?

        第一种(bsearch_1),查找左边界:当我们将区间\left [ l,r \right ]划分成\left [ l,mid \right ]\left [ mid+1,r \right ]时,其更新操作是r=mid或者l=mid+1,计算mid时不需要加1

        第二种(bsearch_2),查找右边界:当我们将区间\left [ l,r \right ]划分成\left [ l,mid-1 \right ]\left [ mid,r \right ]时,其更新操作是r=mid-1或者l=mid,计算mid时需要加1

        注意,两种整数二分查找中的加1减1不要搞混了,什么时候加,什么时候减,什么时候不写要明确,不然会产生死循环!

        两种整数二分查找函数的应用

        例如数组1 2 2 3 3 3 4,如果你想查找数组中的第一个3(红色),就需要用第一种二分查找(查找左边界);如果你想查找数组中的最后一个3(绿色),就需要用第二种二分查找(查找右边界)。


上一篇-求逆序对问题的实现    C++算法基础专栏文章    下一篇-浮点数二分查找的实现


每周六更新一篇文章,内容一般是自己总结的经验或是在其他网站上整理的优质内容

点个赞,关注一下呗~

  • 40
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二分查找是一种高效的查找算法,适用于已经排序好的列表。 实现思路如下: 1. 确定查找范围:首先需要确定要查找的列表的起始索引和结束索引。初始情况下,起始索引为0,结束索引为列表长度减1。 2. 计算中间元素:根据起始和结束索引,计算中间元素的索引。可以使用整数除法来计算中间索引,例如 `mid = (start + end) // 2`。 3. 判断中间元素和目标值的关系:将中间元素与目标值进行比较。如果中间元素等于目标值,则返回中间元素的索引;如果中间元素大于目标值,则说明目标值在中间元素的左侧,更新结束索引为中间索引减1;如果中间元素小于目标值,则说明目标值在中间元素的右侧,更新起始索引为中间索引加1。 4. 重复执行步骤2和步骤3,直到找到目标值或起始索引大于结束索引为止。 5. 如果最终没有找到目标值,则返回一个特定的标识(例如-1)表示未找到。 以下是一个用Python实现二分查找的示例代码: ```python def binary_search(arr, target): start = 0 end = len(arr) - 1 while start <= end: mid = (start + end) // 2 if arr[mid] == target: return mid elif arr[mid] < target: start = mid + 1 else: end = mid - 1 return -1 # 示例使用 arr = [1, 2, 3, 4, 5, 6, 7, 8, 9] target = 6 result = binary_search(arr, target) if result != -1: print("目标值在索引", result) else: print("未找到目标值") ``` 这段代码会输出"目标值在索引5",因为数字6在列表中的索引是5。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值