news 2026/4/17 18:26:25

二分查找神器:lower_bound 函数完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二分查找神器:lower_bound 函数完全指南

前言

在算法竞赛和日常编程中,二分查找是解决搜索问题的利器。C++ STL 中的lower_bound函数将二分查找封装得既优雅又高效。今天我们就来深入剖析这个强大的工具。

什么是 lower_bound?

lower_bound是 C++<algorithm>头文件中的一个函数,用于在有序序列中查找第一个大于等于目标值的元素位置。

基本语法

template< class ForwardIt, class T > ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value );

参数

  • first,last:定义搜索范围的迭代器

  • value:要查找的目标值

返回值

  • 指向第一个≥ value元素的迭代器

  • 如果所有元素都 < value,返回last

直观理解

想象一下,你有一排按身高排序的学生:

[150cm, 155cm, 160cm, 160cm, 165cm, 170cm]

当我们要找第一个≥ 160cm的学生时:

  • lower_bound会指向第一个 160cm 的学生(索引2)

  • 即使后面还有更多 160cm 的学生,它只返回第一个

基本用法示例

#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> nums = {1, 2, 4, 4, 5, 6, 7}; // 查找第一个 >= 4 的元素 auto it = lower_bound(nums.begin(), nums.end(), 4); if (it != nums.end()) { cout << "找到位置: " << (it - nums.begin()) << endl; // 输出: 2 cout << "对应值: " << *it << endl; // 输出: 4 } return 0; }

lower_bound 家族对比

函数功能描述示例(数组[1,3,3,5])返回值
lower_bound第一个targettarget=3第一个3的位置
upper_bound第一个>targettarget=35的位置
binary_search是否存在targettarget=3true(布尔值)
equal_range返回[lower, upper)target=3[第一个3, 5)

可视化演示

数组:[1, 3, 3, 5, 7, 9]

情况1:查找 target = 3
lower_bound 返回 ↑(指向第一个3)
数组:[1, 3, 3, 5, 7, 9]

情况2:查找 target = 4
lower_bound 返回 ↑(指向5)
数组:[1, 3, 3, 5, 7, 9]

情况3:查找 target = 10
lower_bound 返回 end()
数组:[1, 3, 3, 5, 7, 9] end()

实战应用

1.统计元素出现次数

vector<int> nums = {1, 2, 2, 2, 3, 4}; int target = 2; auto left = lower_bound(nums.begin(), nums.end(), target); auto right = upper_bound(nums.begin(), nums.end(), target); int count = right - left; // 3(有3个2) cout << target << "出现了" << count << "次" << endl;

2.在有序数组中插入元素

vector<int> nums = {1, 3, 5, 7}; int new_num = 4; // 找到插入位置(保持有序) auto pos = lower_bound(nums.begin(), nums.end(), new_num); nums.insert(pos, new_num); // 插入到合适位置 // 结果:[1, 3, 4, 5, 7]

3.解决"差值配对"问题

// 问题:统计有多少对数的差等于c int countPairs(vector<int>& nums, int c) { sort(nums.begin(), nums.end()); int ans = 0; for(int i = 0; i < nums.size(); i++) { int target = nums[i] + c; ans += upper_bound(nums.begin(), nums.end(), target) - lower_bound(nums.begin(), nums.end(), target); } return ans; }

注意事项

1.数组必须有序

// 错误示范 vector<int> nums = {5, 1, 3, 2}; auto it = lower_bound(nums.begin(), nums.end(), 3); // 未定义行为! // 正确做法 sort(nums.begin(), nums.end()); // 先排序 auto it = lower_bound(nums.begin(), nums.end(), 3); // 正确

2.获取索引的正确方式

vector<int> nums = {10, 20, 30, 40}; auto it = lower_bound(nums.begin(), nums.end(), 25); if (it != nums.end()) { int index = it - nums.begin(); // 获取索引 // 不要用 distance(),效率较低 }

3.处理找不到的情况

vector<int> nums = {1, 2, 3}; auto it = lower_bound(nums.begin(), nums.end(), 5); if (it == nums.end()) { cout << "所有元素都小于5" << endl; } else { cout << "找到元素:" << *it << endl; }

性能分析

  • 时间复杂度:O(log n)

    • 每次将搜索范围减半

    • 即使处理百万级数据也只需约20次比较

  • 空间复杂度:O(1)

    • 只使用常数额外空间

手动实现 lower_bound

理解原理有助于更好使用:

// 手写 lower_bound 实现 int my_lower_bound(vector<int>& nums, int target) { int left = 0; int right = nums.size(); // 注意:不是 size()-1 while (left < right) { int mid = left + (right - left) / 2; // 防止溢出 if (nums[mid] < target) { left = mid + 1; // 目标在右侧 } else { right = mid; // 目标在左侧或当前位置 } } return left; // 第一个≥target的位置 }

常见面试题应用

1.寻找第一个出现的位置

// 在有序有重复数组中找元素的第一个位置 int firstPosition(vector<int>& nums, int target) { auto it = lower_bound(nums.begin(), nums.end(), target); if (it != nums.end() && *it == target) { return it - nums.begin(); } return -1; }

2.查找插入位置

// LeetCode 35. 搜索插入位置 int searchInsert(vector<int>& nums, int target) { return lower_bound(nums.begin(), nums.end(), target) - nums.begin(); }

3.区间合并

// 将新区间插入到有序区间列表中 vector<vector<int>> insertInterval(vector<vector<int>>& intervals, vector<int>& newInterval) { // 找到插入位置 auto it = lower_bound(intervals.begin(), intervals.end(), newInterval, [](const vector<int>& a, const vector<int>& b) { return a[0] < b[0]; }); intervals.insert(it, newInterval); // ... 后续合并重叠区间 return intervals; }

进阶技巧

1.自定义比较函数

struct Person { string name; int age; }; vector<Person> people = {{"Alice", 20}, {"Bob", 25}, {"Charlie", 25}, {"David", 30}}; // 按年龄查找 auto it = lower_bound(people.begin(), people.end(), 25, [](const Person& p, int age) { return p.age < age; // 自定义比较 });

2.在降序数组中使用

vector<int> nums = {9, 7, 5, 3, 1}; // 在降序数组中查找,需要自定义比较 auto it = lower_bound(nums.begin(), nums.end(), 4, greater<int>()); // 返回指向3的迭代器(第一个≤4的元素?实际上需要重新定义)

性能对比测试

#include <iostream> #include <vector> #include <algorithm> #include <chrono> using namespace std; using namespace chrono; int main() { // 准备100万个数据 vector<int> nums(1000000); for(int i = 0; i < 1000000; i++) { nums[i] = i * 2; // 偶数序列 } // 测试 lower_bound auto start = high_resolution_clock::now(); for(int i = 0; i < 1000; i++) { auto it = lower_bound(nums.begin(), nums.end(), i * 100); } auto end = high_resolution_clock::now(); auto duration = duration_cast<microseconds>(end - start); cout << "1000次查找耗时: " << duration.count() << " 微秒" << endl; cout << "平均每次查找: " << duration.count() / 1000.0 << " 微秒" << endl; return 0; }

最佳实践建议

  1. 总是先排序:使用前确保序列有序

  2. 检查返回值:总是验证返回的迭代器是否有效

  3. 优先使用STL:比手写二分查找更可靠

  4. 注意边界:理解[first, last)的半开半闭区间

  5. 利用类型推导:使用auto简化代码

总结

lower_bound是 C++ 程序员工具箱中的瑞士军刀:

  • 高效:O(log n) 时间复杂度

  • 通用:适用于任何有序序列

  • 安全:STL 实现经过充分测试

  • 灵活:支持自定义比较函数

掌握lower_bound不仅能提高编码效率,更能帮助你深入理解二分查找思想。下次遇到有序数组的查找问题,不妨先想想:能不能用lower_bound解决?


学习资源推荐:

  • C++ Reference: lower_bound

  • 《C++ Primer》第10章:泛型算法

  • LeetCode 练习:35、34、704、278题

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/14 6:38:17

Qwen2.5-7B极简部署:3步搞定,小白也能当AI工程师

Qwen2.5-7B极简部署&#xff1a;3步搞定&#xff0c;小白也能当AI工程师 引言&#xff1a;为什么选择Qwen2.5-7B作为你的第一个AI项目 如果你正在转行求职AI领域&#xff0c;或者想通过一个实际项目提升简历竞争力&#xff0c;Qwen2.5-7B模型是一个绝佳的起点。这个由阿里云开…

作者头像 李华
网站建设 2026/4/18 9:43:48

Qwen2.5-7B自动化脚本:云端定时任务省心省力

Qwen2.5-7B自动化脚本&#xff1a;云端定时任务省心省力 引言 作为一名运营人员&#xff0c;每天手动生成日报是不是让你感到疲惫&#xff1f;想象一下&#xff0c;如果能设置一个自动化系统&#xff0c;让AI在指定时间自动生成日报并发送到你的邮箱&#xff0c;那该有多省心…

作者头像 李华
网站建设 2026/4/18 8:16:04

Qwen2.5-7B远程办公:云端GPU让老家电脑变工作站

Qwen2.5-7B远程办公&#xff1a;云端GPU让老家电脑变工作站 1. 为什么需要云端GPU工作站&#xff1f; 春节回老家发现电脑性能不足&#xff0c;临时项目却要用Qwen2.5大模型&#xff1f;这是很多AI开发者和研究者的真实困境。老家的旧电脑可能连基础编程环境都跑不动&#xf…

作者头像 李华
网站建设 2026/4/17 22:46:07

Qwen2.5-7B企业试用方案:按需付费,零风险评估

Qwen2.5-7B企业试用方案&#xff1a;按需付费&#xff0c;零风险评估 引言&#xff1a;企业AI试用的痛点与解决方案 对于企业技术评估团队来说&#xff0c;测试大语言模型往往面临两难选择&#xff1a;一方面需要充分验证模型性能&#xff0c;另一方面又不想在确认采用前投入…

作者头像 李华
网站建设 2026/4/18 8:46:20

Qwen3-VL视频监控:异常检测部署指南

Qwen3-VL视频监控&#xff1a;异常检测部署指南 1. 引言&#xff1a;Qwen3-VL在智能监控中的应用前景 随着城市安防、工业生产与公共管理对智能化需求的不断提升&#xff0c;视频监控系统正从“看得见”向“看得懂”演进。传统监控依赖人工回溯或简单行为识别算法&#xff0c…

作者头像 李华
网站建设 2026/4/16 14:13:37

Qwen3-VL-WEBUI游戏开发辅助:UI自动生成部署教程

Qwen3-VL-WEBUI游戏开发辅助&#xff1a;UI自动生成部署教程 1. 引言 1.1 游戏开发中的UI痛点 在现代游戏开发流程中&#xff0c;用户界面&#xff08;UI&#xff09;设计与实现是耗时且重复性高的关键环节。从原型设计到代码生成&#xff0c;传统方式依赖设计师与前端工程师…

作者头像 李华