深入二分思想
深入二分思想
二分在实际使用中常常会出现死循环的问题
这是因为我们对二分临界状态的不熟悉而导致的,这里介绍一种通用的分界想法:
整数二分:
int l = begin - 1, r = end + 1; while (l + 1 != r) { int mid = l + r >> 1; if (judge(mid)) l = mid; else r = mid; }
规定当 l + 1 == r
时,退出二分查找,因为在对整数区间进行二分时,最终状态的 l
和 r
是紧密相邻的
judge
函数同样需要进行设计:
1 2 3 4 4 4 5 6
针对以上序列,我们如果想查找:(下标从1开始)
<4 <=4 >4 >=4
的元素下标,那么我们二分的 judge
和 返回的值就不同:
//查找 <4 <=4 时: bool judge(int x){ if (arr[x] < 4) return 1; return 0; } //最终状态的边界线处在3和4之间(下标) //二分最后的l就是3,r就是4(下标)
这样的judge
函数,我们可以查找出 <
和<=
的位置
同样的:
//查找 >4 >=4 时: bool judge(int x){ if (arr[x] <= 4) return 1; return 0; } //最终状态的边界线处在6和7之间(下标) //二分最后的l就是6,r就是7(下标)
这样的judge
函数,我们可以查找出 >
和>=
的位置
在上述的judge
函数中,我们不难写出l
和r
的位置关系,但是为什么只用在judge
中,添加一个=
就能改变查找的方向呢?
还是以这段序列为例:
1 2 3 4 4 4 5 6
查找 <
和<=
时,我们目标是把边界线定位在3
和4
之间
if (arr[x] < 4) return 1;//(l=mid) else return 0;//(r=mid)
因此,当我们的arr[mid]==4
时,我们就要将右边界移动到mid
反之:
查找 >
和>=
时,我们目标是把边界线定位在4
和5
之间
if (arr[x] < 4) return 1;//(l=mid) else return 0;//(r=mid)
因此,当我们的arr[mid]==4
时,我们就要将左边界移动到mid
也可以使用stl
库内的 upper_bound()
和lower_bound()
函数进行二分查找
需要提前对查找的序列进行有序化处理
用法如下:x
为需要查找的元素
//对于静态数组 upper_bound(arr+begin,arr+len,x) lower_bound(arr+begin,arr+len,x) //对于stl容器 upper_bound(arr.begin(),arr.end(),x) lower_bound(arr.begin(),arr.end(),x)
其中,在对静态数组进行查找时,arr+begin
为从第几个元素开始查找,len
为需要查找的区间长度,arr+len
则表示查找到第几个元素停止
upper_bound()
返回的是第一个 大于 x
的迭代器,lower_bound()
返回的是第一个 大于等于 x
的迭代器
对于同样的序列:arr[]={1 2 3 4 4 4 5 6 }
upper_bound(arr, arr+8, 4); lower_bound(arr, arr+8, 4); //通过*解引用处理 cout << *upper_bound(arr, arr + 8, 4) <<' ' << *lower_bound(arr, arr + 8, 4); //输出的结果为 5 4
注意upper_bound()
和lower_bound()
返回的是迭代器,可以通过 -
操作计算他们的绝对距离(大于0),就是等于4
的元素的个数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具