【复习】二分查找

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

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

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

相关推荐
yuanpan2 小时前
Python 调用 DLL 动态库入门:Windows 下调用 C++ 与 C# 动态库完整示例
c++·windows·python
Yzzz-F2 小时前
Problem - D - Codeforces
算法
chas_882 小时前
macbook air M5 32G本地跑ddtree-mlx效果
算法
programhelp_2 小时前
WeRide OA 2026 高频真题分享 & 详细备战指南
经验分享·算法·面试·职场和发展
疯狂打码的少年3 小时前
单向循环链表 + 尾指针:让插入删除更高效的秘密武器
数据结构·python·链表
菜菜的顾清寒3 小时前
Leetcode (18) 力扣100 矩阵置零
算法
董董灿是个攻城狮3 小时前
5分钟搞懂微调的能力退化问题
算法
handler013 小时前
Linux: 基本指令知识点(3)
linux·服务器·c语言·开发语言·c++·笔记
wuminyu3 小时前
专家视角看Java线程生命周期与上下文切换的本质
java·linux·c语言·jvm·c++