lower_bound和upper_bound

本文详细介绍了C++标准库中lower_bound和upper_bound函数的应用方法,包括如何在一个有序区间内进行二分查找,以及如何根据不同的需求调整查找方向。通过实例展示了如何获取目标值在数组中的位置,特别适用于非递减序列的查找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时间复杂度:O(logN)

用法:在一个左闭右开(a,b] 的有序区间里进行二分查找,需要查找的值由第三个参数给出。 

条件:使用这两个函数注意要有序

对于upper_bound来说,返回的是被查序列中第一个大于查找值的指针,也就是返回指向 被查值 > 查找值 的最小指针,lower_bound则是返回的是被查序列中第一个大于等于查找值的指针,也就是返回指向 被查值 >= 查找值 的最小指针。

不过除此之外,这两个函数还分别有一个重载函数,可以接受第四个参数。如果第四个参数传入greater<Type>(),其中Type改成对应类型,那么upper_bound则返回指向 被查值<查找值 的最小指针,lower_bound则返回指向 被查值 <= 查找值 的最小指针。 

 

注意写成lower_bound(a, a+n, x)-a,是从0开始计数;(必须-数组首地址才能得到第一个>=x的数的下标)

 lower_bound(a+1, a+n+1, x)-a,是从1开始计数。

注意:如果用上述两个函数三个参数的那种形式,记得左闭右开的区间要为非递减的顺序,

如果给第四个参数传入greater<Type>(),则区间为非递增的顺序。

 

#include <iostream>
#include <algorithm>
using namespace std;
//返回一个非递减序列 [1,n] 中的第一个 >= x 的位置 
int main()
{
    int a[50];
    int n, x, ans;
    cin >> n >> x;

    for(int i=1; i<=n; i++)
    {
        cin >> a[i];
    }
    ans = lower_bound(a+1, a+n+1, x) - a;
    cout << ans << endl;
    return 0;
}
lower_bound 大于等于 》x的位置

 

#include <iostream>
#include <algorithm>
using namespace std;
//返回一个非递减序列 [1,n] 中的第一个 <= x 的位置
int main()
{
    int a[50];
    int n, x, ans;
    cin >> n >> x;

    for(int i=0; i<n; i++)
    {
        cin >> a[i];
    }
    ans = lower_bound(a, a+n, x, greater<int>()) - a;
    cout << ans << endl;
    return 0;
}
/*
5 3
5 4 3 2 1
2
*/
返回一个非递减序列 [1,n] 中的第一个 <= x 的位置

 


 

 

#include <iostream>
#include <algorithm>
using namespace std;
//返回一个非递减序列 [1,n] 中的第一个 > x 的位置
int main()
{
    int a[50];
    int n, x, ans;
    cin >> n >> x;

    for(int i=0; i<n; i++)
    {
        cin >> a[i];
    }
    ans = upper_bound(a, a+n, x) - a;
    cout << ans << endl;
    return 0;
}
/*
5 3
1 2 3 4 5
3
*/
upper_bound返回一个非递减序列 [1,n] 中的第一个 > x 的位置

 

#include <iostream>
#include <algorithm>
using namespace std;
//返回一个非递减序列 [1,n] 中的第一个 < x 的位置
int main()
{
    int a[50];
    int n, x, ans;
    cin >> n >> x;

    for(int i=0; i<n; i++)
    {
        cin >> a[i];
    }
    ans = upper_bound(a, a+n, x, greater<int>()) - a;
    cout << ans << endl;
    return 0;
}
/*
5 3
5 4 3 2 1
3
*/
返回一个非递减序列 [1,n] 中的第一个 < x 的位置

 

当一个序列里面某个数多次出现:

upper_bound(a,a+n,x)  - lower_bound(a,a+n,x) 得到的是值为x的个数

if(x==2)  1 2 2 2 3 ——> upper_bound(a,a+n,x)  - lower_bound(a,a+n,x)  =  3

#include <iostream>
#include <algorithm>
using namespace std;
//返回一个非递减序列 [1,n] 中的第一个 <= x 的位置
int main()
{
    int a[50];
    int n, x, ans = 0;
    cin >> n >> x;

    for(int i=0; i<n; i++)
    {
        cin >> a[i];
    }
    ans += upper_bound(a, a+n, x) - lower_bound(a, a+n, x) ;
    cout << ans << endl;
    return 0;
}
/*
5 2
1 2 2 2 3
3
*/
挑战程序设计-P161

 

转载于:https://www.cnblogs.com/Roni-i/p/8763886.html

<think>好的,我现在需要帮助用户了解C++ STL中lower_boundupper_bound的用法。用户可能已经接触过mapset这些容器,但不太清楚这两个函数的区别应用场景。首先,我得回顾一下这两个函数的基本定义用途。 根据用户提供的引用资料,特别是引用34,里面提到了upper_bound的用法示例,比如在set中使用upper_bound查找第一个大于key的元素。但用户现在想同时了解lower_boundupper_bound,所以我需要详细解释两者的区别。 首先,lower_bound返回的是第一个大于或等于目标值的元素位置,而upper_bound返回的是第一个大于目标值的元素位置。这在有序容器中非常有用,比如在排序数组、vector、set或map中。这两个函数常用于确定插入位置或者查找元素范围。 接下来,我需要考虑用户可能的实际应用场景。比如在有序区间内插入元素时,可以用lower_bound找到合适的插入点;或者在处理范围查询时,比如统计某个区间内的元素数量,可以用这两个函数确定上下界。例如,用户可能想在一个已排序的vector中找到所有大于等于5且小于10的元素,这时候lower_bound(5)upper_bound(10)就能确定这个区间。 然后,我需要检查用户提供的引用内容是否有相关例子或代码片段。引用3中提到了upper_bound的使用方法,引用4展示了erasefind的结合使用。虽然这些例子没有直接展示lower_bound,但可以结合这些例子来说明两者的区别。例如,在set中,使用lower_bound找到第一个不小于key的元素,而upper_bound则是第一个大于key的,这样在删除某个范围的元素时,可以配合使用这两个函数。 还需要注意这两个函数的时间复杂度,因为它们通常基于二分查找实现,时间复杂度为O(log n),适用于有序容器。但如果是无序结构,比如unordered_map,这两个函数可能不可用,这时候用户可能需要先对容器进行排序,或者使用其他数据结构。 另外,用户可能在处理需要频繁查找插入有序数据的场景中使用这些函数,比如维护一个实时更新的排行榜,或者处理时间序列数据。这时候正确使用lower_boundupper_bound可以提高效率。 最后,我需要确保回答结构清晰,分点说明两者的定义、使用场景、代码示例以及注意事项。同时,根据用户要求生成相关问题,比如它们的区别、应用实例或底层实现原理。这样用户能够全面理解并应用到实际编程中。</think>### C++ STL中lower_boundupper_bound用法解析 #### 一、基础定义与核心差异 1. **lower_bound** 在**有序区间**中返回第一个**大于或等于目标值**的元素迭代器 数学表达式:查找第一个满足$val \geq key$的元素位置 2. **upper_bound** 在**有序区间**中返回第一个**大于目标值**的元素迭代器 数学表达式:查找第一个满足$val > key$的元素位置 ```cpp // 示例:查找有序数组中的范围 vector<int> arr = {1,3,5,7,9}; auto lower = lower_bound(arr.begin(), arr.end(), 5); // 指向5 auto upper = upper_bound(arr.begin(), arr.end(), 5); // 指向7 ``` #### 二、典型应用场景 1. **范围查询** ```cpp // 统计[5,8)区间内的元素数量 set<int> s = {1,3,5,7,9}; auto start = s.lower_bound(5); // 包含5 auto end = s.upper_bound(8); // 不包含8 int count = distance(start, end); // 返回2(5,7) ``` 2. **插入位置确定** ```cpp // 在有序vector中插入元素保持有序性 vector<string> words = {"apple", "banana"}; auto pos = lower_bound(words.begin(), words.end(), "cherry"); words.insert(pos, "cherry"); // 插入到正确位置 ``` 3. **区间删除** ```cpp // 删除所有大于等于3且小于6的元素(引用4的扩展) set<int> myset = {1,2,3,4,5}; myset.erase(myset.lower_bound(3), myset.upper_bound(5)); // 剩余元素:{1,2} ``` #### 三、重要注意事项 1. **容器必须有序** 这两个函数基于二分查找实现,时间复杂度为$O(\log n)$,仅适用于有序容器如`set/map`或已排序的`vector`[^2] 2. **自定义比较函数** ```cpp // 自定义结构体排序规则 struct Person { int age; string name; }; vector<Person> people; // 按年龄升序排列后查找 auto it = lower_bound(people.begin(), people.end(), [](const Person& p, int age){ return p.age < age; }); ``` 3. **返回值验证** 需要检查返回迭代器是否有效,避免越界访问: ```cpp if(lower != container.end()) { // 安全操作 } ``` #### 四、关联容器特例 在`set/map`中可直接调用成员函数: ```cpp set<int> s = {1,3,5}; auto it = s.lower_bound(2); // 返回指向3的迭代器 map<string, int> m; m["apple"] = 5; auto mit = m.upper_bound("app"); // 查找第一个key大于"app"的条目 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值