【复习】二分查找

👨‍💻 关于作者:会编程的土豆

"不是因为看见希望才坚持,而是坚持了才看见希望。"

你好,我是会编程的土豆,一名热爱后端技术的Java学习者。

📚 正在更新中的专栏:

💕作者简介:后端学习者

原始写法:

cpp 复制代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n, m;
vector<int>arr;
int main()
{
	cin >> n >> m;
	arr.resize(n + 5);
	for (int i = 1; i <= n; i++)  cin >> arr[i];
	while (m--)
	{
		int left = 1;
		int right = n;
		int tar; cin >> tar;
		while (left <= right)
		{
			int mid = left + (right - left) / 2;
			if (arr[mid] >= tar)
			{
				right = mid - 1;
			}
			else left = mid + 1;
		}
		if (arr[left] == tar)
			cout << left << " ";
		else cout << "-1"<<" ";
	}
	return 0;
}

二分查找进阶:lower_bound 用法详解(附完整代码 + 易错点分析)

在算法题中,"查找一个数是否存在"是非常高频的需求。

lower_bound 是 C++ STL 中最常用、最强大的二分查找工具之一。

你这段代码就是一个典型模板写法,这篇文章带你彻底理解它。


一、问题描述

给定:

  • 一个长度为 n 的数组

  • m 次查询

对于每个查询 x:

复制代码
如果 x 存在,输出它在数组中的位置(从1开始)
如果不存在,输出 -1

二、代码展示

cpp 复制代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
    int n, m; 
    cin >> n >> m;

    vector<int> arr;
    for (int i = 0; i < n; i++)
    {
        int x; 
        cin >> x;
        arr.push_back(x);
    }

    while (m--)
    {
        int x; 
        cin >> x;

        auto it = lower_bound(arr.begin(), arr.end(), x);

        if (it == arr.end() || *it != x)
        {
            cout << "-1" << " ";
        }
        else
        {
            cout << it - arr.begin() + 1 << " ";
        }
    }
    return 0;
}

三、核心函数:lower_bound

1. 作用

复制代码
返回第一个 >= x 的位置

2. 举个例子

复制代码
数组:1 3 5 7 9
查询 x 返回位置 指向元素
5 2 5
6 3 7
10 end 越界

四、代码逻辑拆解


1. 查找位置

复制代码
auto it = lower_bound(arr.begin(), arr.end(), x);

2. 判断是否存在

复制代码
if (it == arr.end() || *it != x)

含义:

复制代码
1. 到了末尾 → 不存在
2. 找到的不是 x → 不存在

3. 输出位置

复制代码
it - arr.begin() + 1

说明:

复制代码
迭代器转下标 + 转成1-based

五、一个非常重要的前提

复制代码
数组必须是有序的(升序)

⚠️ 如果不排序会发生什么?

复制代码
结果完全错误(但程序不会报错)

正确做法(建议加上)

复制代码
sort(arr.begin(), arr.end());

六、时间复杂度分析


单次查询

复制代码
O(log n)

总复杂度

复制代码
O(n log n + m log n)

七、常见错误总结


1. 忘记排序

最常见错误:

复制代码
lower_bound 默认要求有序

2. 少写判断

错误写法:

复制代码
cout << it - arr.begin();

可能访问非法位置。


3. 忘记 +1

复制代码
it - arr.begin() + 1

八、进阶理解(非常重要)


lower_bound vs upper_bound

函数 含义
lower_bound 第一个 ≥ x
upper_bound 第一个 > x

举例

复制代码
数组:1 2 2 2 3
x lower_bound upper_bound
2 第一个2 第一个3

九、进阶应用(面试常考)


1. 统计某个数出现次数

复制代码
int count = upper_bound(arr.begin(), arr.end(), x)
          - lower_bound(arr.begin(), arr.end(), x);

2. 查找第一个 ≥ x 的位置


十、一句话总结

复制代码
lower_bound = 找到"第一个不小于 x 的位置"

相关推荐
xwz小王子17 分钟前
手术机器人登上Science Robotics:2毫米纤细手臂,从3厘米切口完成腰椎神经减压
算法·机器人
黎阳之光1 小时前
视频孪生智护供水生命线:黎阳之光赋能医疗与园区水务高质量升级
运维·物联网·算法·安全·数字孪生
Black蜡笔小新2 小时前
自动化AI算法训练服务器DLTM制造业AI质检工作站助力制造业实现AI智检
人工智能·算法·自动化
嵌入式小能手2 小时前
飞凌嵌入式ElfBoard-进程间的通信之命名管道
linux·服务器·算法
啦哈拉哈2 小时前
Leetcode题解记录-hot100(81-100)
算法·leetcode·职场和发展
csdn_aspnet2 小时前
Java 霍尔分区算法(Hoare‘s Partition Algorithm)
java·开发语言·算法
王老师青少年编程2 小时前
信奥赛C++提高组csp-s之搜索进阶(搜索剪枝核心思想 )
c++·dfs·csp·信奥赛·搜索剪枝·搜索优化
一拳一个呆瓜2 小时前
【STL】使用 C++ 标准库标头
c++·stl
诸葛务农3 小时前
道路行驶条件下电动汽车永磁电机的有效使用寿命及永磁体的失效和回收再利用(下)
java·开发语言·算法
snow@li3 小时前
AI:理解 大数据、算法、算力、电力、生成式AI、token 之间的关系
大数据·人工智能·算法