C++ STL: lower_bound 和 upper_bound 的用法及区别

在 C++ 标准模板库(STL)中,std::lower_boundstd::upper_bound 是两个强大的二分查找函数,适用于 有序范围(如 std::vectorstd::setstd::map)。这两个函数可以帮助我们快速找到元素的位置,支持高效的插入、统计和查找操作。

lower_boundupper_bound 的区别

std::lower_bound

  • 作用: 返回第一个 大于等于 (>=) 指定值的元素的迭代器。
  • 如果值存在: 返回该值的第一个位置。
  • 如果值不存在: 返回比目标值 大的第一个元素 位置。
  • 如果所有元素都小于目标值: 返回 end() 迭代器。
  • 反向查找小于目标值的元素: std::lower_bound 返回的迭代器减一,即 std::lower_bound(vec.begin(), vec.end(), target) - 1

std::upper_bound

  • 作用: 返回第一个 大于 (>) 指定值的元素的迭代器。
  • 如果值存在: 跳过所有相同值,返回比目标值 大的第一个元素 位置。
  • 如果值不存在: 返回比目标值 大的第一个元素 位置。
  • 如果所有元素都小于等于目标值: 返回 end() 迭代器。
  • 反向查找小于等于目标值的元素: std::upper_bound 返回的迭代器减一,即 std::upper_bound(vec.begin(), vec.end(), target) - 1

示例代码

虽然标准库只提供了“大于”和“大于等于”的函数,但是用这两个函数,可以组合出“小于”,“小于等于”和“等于”的判定。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {1, 2, 4, 4, 4, 6, 8, 10};
    int target = 4;

    // lower_bound
    auto lower = std::lower_bound(vec.begin(), vec.end(), target);
    std::cout << "lower_bound of " << target << " is at index: " << (lower - vec.begin()) << std::endl;

    // upper_bound
    auto upper = std::upper_bound(vec.begin(), vec.end(), target);
    std::cout << "upper_bound of " << target << " is at index: " << (upper - vec.begin()) << std::endl;

    // 找到最后一个小于 target 的元素
    if (lower != vec.begin()) {
        auto last_less = lower - 1;
        std::cout << "Last element less than " << target << " is " << *last_less << " at index " << (last_less - vec.begin()) << std::endl;
    } else {
        std::cout << "No element is less than " << target << std::endl;
    }

    // 找到最后一个小于等于 target 的元素
    if (upper != vec.begin()) {
        auto last_less_equal = upper - 1;
        std::cout << "Last element less than or equal to " << target << " is " << *last_less_equal << " at index " << (last_less_equal - vec.begin()) << std::endl;
    } else {
        std::cout << "No element is less than or equal to " << target << std::endl;
    }

    return 0;
}

运行结果

lower_bound of 4 is at index: 2
upper_bound of 4 is at index: 5
Last element less than 4 is 2 at index 1
Last element less than or equal to 4 is 4 at index 4

示例和拓展

1. 查找元素是否存在

if (lower != vec.end() && *lower == target) {
    std::cout << target << " exists in the array at index " << (lower - vec.begin()) << std::endl;
} else {
    std::cout << target << " does not exist in the array." << std::endl;
}

2. 统计目标值出现次数

int count = upper - lower;
std::cout << "Count of " << target << " is: " << count << std::endl;

3. 查找最后一个小于目标值的元素

if (lower != vec.begin()) {
    auto last_less = lower - 1;
    std::cout << "Last element less than " << target << " is " << *last_less << std::endl;
}

4. 查找最后一个小于等于目标值的元素

if (upper != vec.begin()) {
    auto last_less_equal = upper - 1;
    std::cout << "Last element less than or equal to " << target << " is " << *last_less_equal << std::endl;
}

复杂度分析

  • std::lower_boundstd::upper_bound 都基于二分查找,时间复杂度为 O(log n)
  • 适用于 有序序列,如果无序,则需要先排序 O(n log n),然后查找 O(log n)

总结

函数 返回 若值存在 若值不存在 典型应用
lower_bound 第一个 >= target 的迭代器 目标值的第一个位置 第一个比它大的元素 查找元素、插入位置
upper_bound 第一个 > target 的迭代器 跳过所有相同值的元素 第一个比它大的元素 计算元素出现次数
lower_bound - 1 最后一个 < target 的迭代器 目标值前一个元素 最大的小于 target 的元素 反向查找小于目标值
upper_bound - 1 最后一个 <= target 的迭代器 目标值最后一个位置 最大的小于等于 target 的元素 反向查找小于等于目标值
posted @ 2025-01-31 13:00  Ofnoname  阅读(387)  评论(0编辑  收藏  举报