C++ lower_bound & upper_bound
前言
C++ 中 lower_bound 和 upper_bound 的实现原理皆为二分。引用时追加头文件 algorithm
又因为在一个数组中二分的前提是数组本身具有单调性,所以在使用这两个函数之前请保证查询数组的单调性哦。
正文
lower_bound
lower_bound 函数返回的是给定数组中第一个大于等于某个元素的位置。
Eg. lower_bound(a + 1, a + n + 1, x) 返回的就是 \(a\) 数组中 \(1 \sim n\) 的第一个大于等于 \(x\) 的数的位置。
这里有一个坑点,lower_bound 函数返回的是数组中的地址,所以我们又如下改动:
lower_bound(a + 1, a + n + 1, x) - a
最后的 \(a\) 不是表示数组名,而是数组 \(a\) 中第一个位置的地址。
如果你不想怎么麻烦,那么你可以改成这样:
*lower_bound(a + 1, a + n + 1, x)
效果都是一样,前面加 * 就相当于直接返回位置,而不是地址
例题代码:找到数组 \(a\) 中第一个大于等于 \(x\) 的数的位置。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100005; // 数组大小
int n, a[N], x;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
scanf("%d", &x);
int pos = lower_bound(a + 1, a + n + 1, x) - a; // 调用 lower_bound 函数
/* 也可以省略上面这一行,直接输出 *lower_bound(a + 1, a + n + 1, x) */
printf("%d", pos);
return 0;
}
输入:
5
1 2 3 4 5
3
输出
3
upper_bound
与 lower_bound 相似,但是 upper_bound 返回的是数组中第一个大于给定数组中的某个元素的位置。
Eg. upper_bound(a + 1, a + n + 1, x) 返回的就是 \(a\) 数组中 \(1 \sim n\) 的第一个大于 \(x\) 的数的位置。
upper_bound 的使用方式和 lower_bound 是一样的。
例题代码:找到数组 \(a\) 中第一个大于 \(x\) 的数的位置。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100005; // 数组大小
int n, a[N], x;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
scanf("%d", &x);
int pos = upper_bound(a + 1, a + n + 1, x) - a; // 调用 upper_bound 函数
/* 也可以省略上面这一行,直接输出 *upper_bound(a + 1, a + n + 1, x) */
printf("%d", pos);
return 0;
}
输入:
5
1 2 3 4 5
3
输出
3
结尾
lower_bound 和 upper_bound 作为 C++ Std 模板库中实用性较强的函数,还是强力推荐的。最后附上 lower_bound 和 upper_bound 的等价的二分代码,毕竟原理也是重要的。
// lower_bound
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100005; // 数组大小
int n, a[N], x;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
scanf("%d", &x);
int le = 1, ri = n; // 左边界和右边界
while (le <= ri) {
int mid = (le + ri) >> 1;
if (a[mid] >= x) ri = mid - 1; // 大于等于,去左边找第一个大于等于 x 的数
else le = mid + 1;
}
printf("%d", le);
return 0;
}
// upper_bound
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100005; // 数组大小
int n, a[N], x;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
scanf("%d", &x);
int le = 1, ri = n; // 左边界和右边界
while (le <= ri) {
int mid = (le + ri) >> 1;
if (a[mid] > x) ri = mid - 1; // 大于等于,去左边找第一个大于等于 x 的数
else le = mid + 1;
}
printf("%d", le);
return 0;
}

浙公网安备 33010602011771号