整数二分查找
二分模板一共有两个,分别适用于不同情况。
算法思路:
假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值。
***注意:
当l=mid时,mid=l+r+1;
当r=mid时,mid=l+r;
根据后面判断前面。
模版1:
当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
代码:
//查找左边界 SearchLeft 简写SL
int SL(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;// 最后r=l
}
模版2:
当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。
代码:
//查找右边界 SearchRight 简写SR
int SR(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1; //需要+1 防止死循环
if (check(mid)) l = mid;
else r = mid - 1;
}
return r; // 最后r=l
}
具体例题:
返回查找的数的位置,若没有就返回“-1”;
代码:
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int q[N];
int SL(int l, int r, int x) {
while (l < r) {
int mid = l + r >> 1;
if (q[mid] >= x) r = mid;
else l = mid + 1;
}
return l;
}
int SR(int l, int r, int x) {
while (l < r) {
int mid = l + r + 1 >> 1;
if (q[mid] <= x) l = mid;
else r = mid - 1;
}
return r;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; ++i) scanf("%d", &q[i]);
while (m--) {
int x;
scanf("%d", &x);
int l = SL(0, n - 1, x);//查找左边界 并返回下标l
if (q[l] != x) cout << "-1 -1" << endl;//如果找不到 返回-1 -1
else {
cout << l << ' '; //如果找到了 输出左下标
cout << SR(0, n - 1, x) << endl; //输出右下标
}
}
return 0;
}