【复习】二分查找

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

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

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

相关推荐
沫璃染墨33 分钟前
从零入门计算机网络系列(十二):HTTP长连接与会话管理详解——从Connection到Cookie与Session
linux·服务器·c++·tcp/ip·ubuntu·http·交互
nm_zfyjt37 分钟前
信息流广告投放优化实践:线索成本评估模型与转化链路重构(家装建材案例)
算法·重构·内蒙古朋友圈广告服务商·内蒙古朋友圈获客
xiaoye-duck2 小时前
《C++ 项目:手写大模型接入 SDK》DeepSeek接口设计(下):流式响应实现和测试
开发语言·网络·c++·语言模型
w_zero_one2 小时前
算法--构造
java·数据结构·算法
其实防守也摸鱼2 小时前
信创安全竞赛知识总结与题库
大数据·网络·人工智能·算法·安全·php
旖旎夜光3 小时前
【C++ 基础入门】类和对象(上):封装、对象模型与 this 指针
开发语言·c++·笔记·学习
小超人诞生日记4 小时前
C++ 智能指针的使用及其原理详解
c++·算法
akinggw5 小时前
libagentcore - 一个基于c++的AI多agent系统升级到2.0版本
开发语言·jvm·c++
繁星蓝雨5 小时前
C++设计原理———多重继承(虚基类、菱形继承、委托、重命名、基类和成员初始化)
c++·委托·多重继承·mi·显式初始化列·虚基类·对象布局