在 C++ 标准模板库(STL)中,std::lower_bound
和 std::upper_bound
是两个强大的二分查找函数,适用于 有序范围(如 std::vector
、std::set
或 std::map
)。这两个函数可以帮助我们快速找到元素的位置,支持高效的插入、统计和查找操作。
lower_bound
和 upper_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; |
| |
| |
| auto lower = std::lower_bound(vec.begin(), vec.end(), target); |
| std::cout << "lower_bound of " << target << " is at index: " << (lower - vec.begin()) << std::endl; |
| |
| |
| auto upper = std::upper_bound(vec.begin(), vec.end(), target); |
| std::cout << "upper_bound of " << target << " is at index: " << (upper - vec.begin()) << std::endl; |
| |
| |
| 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; |
| } |
| |
| |
| 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_bound
和 std::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 的元素 |
反向查找小于等于目标值 |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步