C++ lower_bound & upper_bound

前言

C++ 中 lower_boundupper_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_boundupper_bound 作为 C++ Std 模板库中实用性较强的函数,还是强力推荐的。最后附上 lower_boundupper_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;
}
posted @ 2025-03-28 20:56  Panda_LYL  阅读(81)  评论(0)    收藏  举报