二分查找(整数二分)
一、算法简介
二分法,即二分搜索法,是通过不断缩小解可能存在的范围,从而求得问题最优解的方法。
例如,如果一个序列是有序的,那么可以通过二分的方法快速找到所需要查找的元素,相比线性搜索要快不少。
此外二分法还能高效的解决一些单调性判定的问题。
- 二分的关键不在于单调性,或者说二分的本质并不是单调性。
- 二分的本质是能否找到一个性质使得左右两个区间的元素分别满足性质和不满足性质。
- 二分到最后一定可以得到一个结果,
l
和r
是相同的,但是要判断是否满足题目条件。
二分算法思路非常简单,但是我们需要特别注意的是下标问题,相信很多人都会遇到二分死循环的问题,所以建议大家背一个模板,又快又准确,保证不会出错的解题。
以下介绍两个模板,区别仅在于l = mid
时,mid
需要加一,否则会出现死循环:
区间分为:[l, mid]和[mid + 1, r]
while (l < r)
{
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
区间分为:[l, mid - 1]和[mid, r]
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
二、题目描述
给定一个按照升序排列的长度为
对于每个查询,返回一个元素
如果数组中不存在该元素,则返回 -1 -1
。
输入格式
第一行包含整数
第二行包含
接下来
输出格式
共
如果数组中不存在该元素,则返回 -1 -1
。
数据范围
输入样例:
6 3
1 2 2 3 3 4
3
4
5
输出样例:
3 4
5 5
-1 -1
三、题目来源
四、算法思路
- 对于第一轮找起始位置,也就是找到
≥x
的最小值,所以可以将区间分为左区间<x
,右区间≥x
- 第一轮二分之后要判断是否满足条件,因为有可能数组中没有这个数,这个时候就要根据题目要求进行判断。
- 对于第二轮找终止位置,也就是找到
≤x
的最大值,所以可以将区间分为左区间≤x
,右区间>x
。
五、源码
#include <iostream>
using namespace std;
const int N = 100010;
int n, q;
int a[N];
int main()
{
cin >> n >> q;
for (int i = 0; i < n; ++i) cin >> a[i];
while (q -- )
{
int x;
cin >> x;
int l = 0, r = n - 1;
while (l < r)
{
int mid = (l + r) >> 1;
if (a[mid] >= x) r = mid;
else l = mid + 1;
}
if (a[l] != x) cout << "-1 -1" << endl;
else
{
cout << l << ' ';
int l = 0, r = n - 1;
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (a[mid] <= x) l = mid;
else r = mid - 1;
}
cout << r << endl;
}
}
return 0;
}
合集:
1-1.基础算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具