【复习】二分查找

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

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

你好,我是会编程的土豆,一名热爱后端技术的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 的位置"

相关推荐
汉克老师1 小时前
GESP6级C++考试语法知识(四、图与树(四))
c++·贪心算法·优先队列·哈夫曼编码·哈夫曼树·gesp6级·gesp六级
宝贝儿好1 小时前
【LLM】第三章:项目实操案例:智能输入法项目
人工智能·python·深度学习·算法·机器人
子兮曰2 小时前
whisper.cpp 深度解析:从边缘设备到实时语音识别
前端·c++·后端
雪碧聊技术2 小时前
上午题_算法
算法·软考·软件设计师
特种加菲猫2 小时前
二叉搜索树:数据世界的“快速寻路指南”
开发语言·c++
naturerun2 小时前
从数组中删除元素的算法
数据结构·c++·算法
特种加菲猫2 小时前
STL关联容器:Set/Multiset与Map/Multimap详解
开发语言·c++
Andy2 小时前
C++ list容器基本逻辑结构详解
c++·windows·list
斯内科3 小时前
四胞胎素数:找出‌个位数分别是 1、3、7、9‌,且‌十位及更高位数字完全相同‌的质数,例如 11、13、17、19
算法·质数·素数·四胞胎素数