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

news/2025/1/31 13:01:25/文章来源:https://www.cnblogs.com/ofnoname/p/18695722

在 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_boundauto lower = std::lower_bound(vec.begin(), vec.end(), target);std::cout << "lower_bound of " << target << " is at index: " << (lower - vec.begin()) << std::endl;// upper_boundauto 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 的元素 反向查找小于等于目标值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/877263.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kuboard作为k8s的dashboard使用

kuboard作为k8s的dashboard使用 1 资源信息主机名 OS IP CPU/MEMERY/DISK 备注k8s-master Rocky-8.10 172.16.1.30 2core/4GiB/100GiB k8s-v1.28.0k8s-node01 Rocky-8.10 172.16.1.31 4core/8GiB/100GiB k8s-v1.28.0k8s-node02 Rocky-8.10 172.16.1.32 4core/8GiB/100GiB k8s-v…

Python GIL(全局解释器锁)机制对多线程性能影响的深度分析

在Python开发领域,GIL(Global Interpreter Lock)一直是一个广受关注的技术话题。在3.13已经默认将GIL去除,在详细介绍3.13的更亲前,我们先要留了解GIL的技术本质、其对Python程序性能的影响。本文将主要基于CPython(用C语言实现的Python解释器,也是目前应用最广泛的Pyth…

java中的ArrayBlockingQueue

ArrayBlockingQueue ArrayBlockingQueue 是 Java 并发包 (java.util.concurrent) 中的一个线程安全的阻塞队列实现。 它基于数组实现,容量固定,支持先进先出的顺序。 Array Blocking Queue 数组阻塞队列 读音: [əˈreɪ] [ˈblɒkɪŋ] [kjuː] concurrent 同时发生的 /…

五. Redis 配置内容(详细配置说明)

五. Redis 配置内容(详细配置说明) @目录五. Redis 配置内容(详细配置说明)1. Units 单位配置2. INCLUDES (包含)配置3. NETWORK (网络)配置3.1 bind(配置访问内容)3.2 protected-mode (保护模式)3.3 port(端口)配置3.4 timeout(客户端超时时间)配置3.5 tcp-keepalive()配置4…

一文搞懂编程在开源软件运动中的应用

一文搞懂编程在开源软件运动中的应用一文搞懂编程在开源软件运动中的应用一理解开源软件运动文本内容开源软…………```HTML一文搞懂编程在开源软件运动中的应用一、理解开源软件运动:<!DOCTYPE html><html><head><meta charset="UTF-8"> &…

makefile在编译后输出STM32的Flash RAM占用情况的方法

本文介绍了在用makefile组织的STM32工程中,怎么在编译完成后计算并显示Flash和RAM占用情况的方法。知乎 - STM32 GCC工程编译后输出FLASH RAM使用占比的方法 里面这个方法看得我血压飙升,本身代码很不直观,写起来要反斜杠,还留了两行没用的代码,还有各种依赖命令,subst和…

您的干净代码可能是别人的技术债务

您的干净代码可能是别人的技术债务 为什么软件模式必须适应团队规模,以及如何正确操作。 大卫罗德纳斯 博士由作者生成 在软件开发中,我们面临着一个奇怪的悖论:对于一个团队来说,使代码更干净、更易维护、更优雅的架构决策,可能会让另一个团队觉得更复杂、更僵化、更麻烦…

读算法简史:从美索不达米亚到人工智能时代02古老的算法

苏美尔文字起源于湿黏土陶筹,楔形文字记录了苏美尔语,促进社会发展。阿卡德、巴比伦帝国相继统治,文字变迁。19世纪欧洲考古学家破译文字。美索不达米亚算法复杂,包括六十进制和毕达哥拉斯定理。埃及数学留存少,欧几里得算法著名。1. 苏美尔 1.1. 位于苏美尔地区的乌鲁克,…

计量经济学——空间计量概述(十八)

img { display: block; margin-left: auto; margin-right: auto } table { margin-left: auto; margin-right: auto } 空间计量经济学(Spatial Econometrics)创新性地解决了经典计量方法在空间数据分析中的局限性,研究地理观测值之间的相互关系。近年来,在人文社会科学的“…