二分法的正确写法

二分查找的正确实现关键在于理解循环不变式。初始化、保持和终止是确保算法正确性的三个阶段。文章分析了不同场景下的二分查找应用,包括查找第一个等于key的元素、最后一个等于key的元素等,并解释了为何`while(l != r)`是合适的终止条件,帮助解决二分查找可能导致的死循环问题。
摘要由CSDN通过智能技术生成

综述

二分查找的思想并不难理解,但是想要写出正确的二分算法很困难,困难主要来自于循环不变式的正确性不好把握。
想要建立一个正确的循环不变式,需要牢牢把握好三部分的内容:
初始化:它在循环的第一轮迭代开始之前,应该是正确的。
保持:如果在循环的某一次迭代开始之前它是正确的,那么,在下一次迭代开始之前,它也应该保持正确。
终止:循环能够终止,并且可以得到期望的结果。
这里举出各种二分查找的变种,结合特定算法即可理解上述三个阶段的要点:

情形分析

  1. 查找第一个与key相等的元素(lower_bound且=key)
template<typename T1, typename T2>
T1 my_binary_search(const T1& begin, const T1& end, const T2& key)
{
   
	T1 l = begin, r = end, m;
	while (l != r)//本循环最终必然会将问题规模缩减至1
	{
   
		m = l + ((r - l) >> 1);//写成这种形式可以避免l和r较大时相加溢出
		*m < key ? l = ++m : r = m;//+1确保l必然会前进,最终落到=key或者key后面一个元素(key不存在时)的位置
	}
	//无须检测是否小于begin,因为不存在前向的减法操作
	return (l != end && *l == key) ? l : end;//本问题需要检测目标位置与key是否相符
}
  1. 查找最后一个与key相等的元素(upper_bound的前一个且=key)
template<typename T1, typename T2>
T1 my_binary_search(const T1& begin, const T1& end, const T2&a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值