【算法精讲】二分查找 核心模板与边界处理实战

发布时间:2026/7/15 8:58:45

【算法精讲】二分查找 核心模板与边界处理实战
1. 二分查找算法基础入门二分查找是计算机科学中最基础也最实用的算法之一。我第一次接触这个算法是在大学的数据结构课上当时觉得这个算法简直太神奇了——它能在O(log n)的时间复杂度内完成查找比线性查找快得多。但真正开始刷题后才发现看似简单的二分查找藏着不少坑。二分查找的核心思想很简单对于一个有序数组每次通过比较中间元素和目标值的大小关系将搜索范围缩小一半。这个过程就像我们小时候玩的猜数字游戏对方心里想一个1-100的数字你每次猜中间值对方告诉你大了还是小了这样最多7次就能猜中。但实际应用中二分查找的变体很多比如查找精确值查找左边界第一个等于目标值的位置查找右边界最后一个等于目标值的位置查找近似值最接近目标值的位置这些变体虽然核心思想相同但在边界条件处理上各有特点。很多初学者包括当年的我经常在这些细节上栽跟头比如循环条件是left right还是left rightmid计算时要不要加1更新边界时是mid还是mid±12. 整数二分查找的两种核心模板经过大量练习和踩坑后我总结出了两种最常用的整数二分模板分别对应查找左边界和右边界的情况。这两种模板几乎可以解决所有整数二分问题。2.1 查找左边界的模板// 查找左边界返回第一个target的元素位置 int searchLeft(int l, int r) { while (l r) { int mid l (r - l) / 2; // 防止溢出 if (check(mid)) { // 通常为nums[mid] target r mid; } else { l mid 1; } } return l; // 结束时lr }这个模板的特点是循环条件是l r结束时l和r相等mid计算不需要加1当check(mid)为真时rmid否则lmid1实际应用示例AcWing 789. 数的范围int SL(int l, int r, int x) { while (l r) { int mid l r 1; if (q[mid] x) r mid; else l mid 1; } return l; }2.2 查找右边界的模板// 查找右边界返回最后一个target的元素位置 int searchRight(int l, int r) { while (l r) { int mid l (r - l 1) / 2; // 注意这里要1 if (check(mid)) { // 通常为nums[mid] target l mid; } else { r mid - 1; } } return r; // 结束时lr }这个模板的不同之处在于mid计算需要加1防止死循环当check(mid)为真时lmid否则rmid-1实际应用示例AcWing 789. 数的范围int SR(int l, int r, int x) { while (l r) { int mid l r 1 1; if (q[mid] x) l mid; else r mid - 1; } return r; }2.3 两种模板的选择技巧如何快速判断该用哪个模板我的经验是先明确要找的是左边界还是右边界画图分析check(mid)为真时应该更新哪个边界根据边界更新方式决定mid是否要1举个例子在AcWing 789中找左边界时我们希望尽可能向左移动所以当q[mid]x时更新右边界找右边界时我们希望尽可能向右移动所以当q[mid]x时更新左边界3. 边界条件与常见错误分析二分查找的难点不在于算法本身而在于各种边界条件的处理。下面是我总结的几个常见错误和解决方法3.1 死循环问题最典型的错误是查找右边界时忘记mid1导致死循环。比如// 错误示例可能陷入死循环 int SR(int l, int r) { while (l r) { int mid l r 1; // 忘记1 if (q[mid] x) l mid; // 当lr-1时会卡住 else r mid - 1; } return r; }解决方法当更新lmid时必须确保mid计算时有1。3.2 越界问题另一个常见错误是初始边界设置不当导致越界。比如数组长度为0时r初始为-1或者查找不存在的元素时返回了非法索引。解决方法检查输入数组是否为空检查返回值是否在合法范围内添加边界条件判断3.3 精度问题浮点数二分虽然这部分主要讨论整数二分但浮点数二分也有类似问题。常见错误是精度设置不当导致循环无法终止或结果不精确。解决方法根据题目要求设置合适的精度eps固定循环次数如循环100次也是一种可行方案4. 实战应用与题目解析4.1 AcWing 789. 数的范围这道题完美展示了二分查找左右边界的应用。解题步骤使用searchLeft找到第一个x的位置检查该位置是否确实等于x如果等于x再用searchRight找到最后一个x的位置输出两个位置完整代码#include iostream using namespace std; const int N 1e5 10; int q[N]; int SL(int l, int r, int x) { while (l r) { int mid l r 1; if (q[mid] x) r mid; else l mid 1; } return l; } int SR(int l, int r, int x) { while (l r) { int mid l r 1 1; if (q[mid] x) l mid; else r mid - 1; } return r; } int main() { int n, m; scanf(%d%d, n, m); for (int i 0; i n; i) scanf(%d, q[i]); while (m--) { int x; scanf(%d, x); int l SL(0, n - 1, x); if (q[l] ! x) cout -1 -1 endl; else { cout l ; cout SR(0, n - 1, x) endl; } } return 0; }4.2 AcWing 790. 数的三次方根这道题展示了浮点数二分的应用。注意点精度控制题目要求保留6位小数eps一般设为1e-8边界设置注意x可能为负数的情况代码示例#include iostream using namespace std; double n; int main() { cin n; double l -10000, r 10000; while (r - l 1e-8) { double mid (l r) / 2; if (mid * mid * mid n) r mid; else l mid; } printf(%.6lf\n, l); return 0; }5. STL中的二分查找函数C标准库提供了几个二分查找相关函数了解它们可以帮助我们快速解决一些问题lower_bound返回第一个target的元素位置upper_bound返回第一个target的元素位置binary_search判断元素是否存在使用示例AcWing 789的STL版本#include bits/stdc.h using namespace std; void solve(int k, vectorint v) { int l lower_bound(v.begin(), v.end(), k) - v.begin(); int r upper_bound(v.begin(), v.end(), k) - v.begin(); if (v[l] k) printf(%d , l); else printf(-1 ); if (v[r - 1] k) printf(%d\n, r - 1); else printf(-1\n); } int main() { int n, q, k, tmp; cin n q; vectorint v; for (int i 0; i n; i) { cin tmp; v.push_back(tmp); } while (q--) { cin k; solve(k, v); } return 0; }6. 调试技巧与性能优化6.1 调试技巧打印中间值在循环中加入打印语句观察l, r, mid的变化小数据测试用小的测试用例手动模拟算法执行过程边界测试测试空数组、单元素数组等特殊情况6.2 性能优化使用位运算代替除法mid (l r) 1避免不必要的函数调用对于频繁调用的check函数可以考虑内联7. 常见问题与解决方案在实际刷题过程中我遇到过各种二分查找的问题。这里分享几个典型问题和解决方法如何判断该用哪个模板先明确要找的是左边界还是右边界画图分析check条件为什么我的代码陷入了死循环检查mid计算是否需要1检查边界更新是否正确如何处理重复元素找左边界用第一个target的模板找右边界用最后一个target的模板浮点数二分如何设置精度一般比题目要求多2位或者使用固定循环次数8. 进阶练习推荐为了巩固二分查找技能我推荐以下练习题LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置LeetCode 35. 搜索插入位置AcWing 1221. 四平方和AcWing 1227. 分巧克力AcWing 730. 机器人跳跃问题每道题都有其特点比如四平方和需要结合哈希表分巧克力需要考虑如何设计check函数机器人跳跃问题需要转化问题模型记住二分查找的核心在于二分的思想而不仅仅是代码模板。很多问题看似与查找无关但可以通过巧妙的建模转化为二分查找问题。这需要大量的练习和经验积累。

相关新闻

从“一般故障”到精准定位:一次Ping测试背后的网络层深度排查

从“一般故障”到精准定位:一次Ping测试背后的网络层深度排查

2026/7/15 8:58:45

1. 当Ping命令返回"一般故障"时,我们到底在说什么?"一般故障"这个看似简单的提示背后,隐藏着操作系统网络协议栈的复杂运作机制。不同于"请求超时"或"目标主机不可达"这类明确指向特定问题的错误&am…

从末流985到顶尖学府:通信电子保研实战复盘与避坑指南

从末流985到顶尖学府:通信电子保研实战复盘与避坑指南

2026/7/15 8:58:45

1. 保研前的三年准备:从迷茫到清晰记得刚进入大学时,我对保研这件事完全没概念。直到大一下学期,偶然听到学长分享保研经验,才意识到原来还有这样一条升学路径。作为一个末流985的学生,我深知要逆袭顶尖院校&#xff0…

小米智能音箱Pro深度评测:音质与智能家居控制体验

小米智能音箱Pro深度评测:音质与智能家居控制体验

2026/7/15 8:48:45

蓝牙音箱推荐:MI小米智能音箱Pro,音质与智能兼具的深度体验在智能家居快速普及的今天,蓝牙音箱已经成为家庭娱乐和智能控制的重要入口。作为一名长期关注智能设备的技术博主,我最近深度体验了小米智能音箱Pro,发现它在…

信息安全系统中真随机数生成技术解析与应用

信息安全系统中真随机数生成技术解析与应用

2026/7/15 10:38:50

1. 为什么信息安全系统需要真随机数?在信息安全领域,随机数就像建筑的地基。2017年WannaCry勒索病毒事件中,安全专家发现攻击者使用的伪随机数生成算法存在漏洞,这直接导致全球30多万台电脑被攻陷。这个案例生动展示了随机数质量对…

Yuzu模拟器架构解析:高性能Switch游戏模拟解决方案深度指南

Yuzu模拟器架构解析:高性能Switch游戏模拟解决方案深度指南

2026/7/15 10:38:50

Yuzu模拟器架构解析:高性能Switch游戏模拟解决方案深度指南 【免费下载链接】yuzu-downloads 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu-downloads Yuzu作为目前最先进的Nintendo Switch开源模拟器,通过创新的架构设计和技术实现&…

TI CC2640R2F-Q1低功耗蓝牙MCU设计实战:ADC、传感器控制器与电源管理详解

TI CC2640R2F-Q1低功耗蓝牙MCU设计实战:ADC、传感器控制器与电源管理详解

2026/7/15 10:38:50

1. 项目概述与核心价值在物联网和可穿戴设备领域,我们开发者最头疼的问题之一,就是如何在有限的电池容量下,让设备“活”得更久。这不仅仅是选一个低功耗芯片那么简单,它是一场从硬件选型、电源架构设计到软件策略优化的系统性战役…

PromptForge:终极AI提示工程工作台 - 10个技巧快速提升提示质量

PromptForge:终极AI提示工程工作台 - 10个技巧快速提升提示质量

2026/7/15 10:38:50

PromptForge:终极AI提示工程工作台 - 10个技巧快速提升提示质量 【免费下载链接】prompt-forge AI prompt engineering workbench for crafting, testing, and systematically evaluating prompts with powerful analysis tools. 项目地址: https://gitcode.com/g…

STM32 GPIO输入模式与外部中断配置详解

STM32 GPIO输入模式与外部中断配置详解

2026/7/15 10:38:50

1. STM32输入模式基础解析在嵌入式开发中,GPIO(通用输入输出)是最基础也是最常用的外设之一。STM32的GPIO可以配置为多种工作模式,其中输入模式是接收外部信号的关键。理解这些模式的区别和适用场景,是进行可靠硬件交互…

gibMacOS终极指南:3步从Apple官方服务器下载macOS安装组件

gibMacOS终极指南:3步从Apple官方服务器下载macOS安装组件

2026/7/15 10:28:50

gibMacOS终极指南:3步从Apple官方服务器下载macOS安装组件 【免费下载链接】gibMacOS Py2/py3 script that can download macOS components direct from Apple 项目地址: https://gitcode.com/gh_mirrors/gi/gibMacOS gibMacOS是一款强大的跨平台工具&#x…

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

2026/7/14 10:03:09

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator XUnity.AutoTranslator作为Unity游戏社区中最成熟的文本翻译解决方…

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

2026/7/13 20:43:19

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持 【免费下载链接】raspberrypi-kernel It provides openEuler kernel source for Raspberry Pi 项目地址: https://gitcode.com/openeuler/raspberrypi-kernel 前往项目官网免费下载&…

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

2026/7/15 0:26:43

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧 【免费下载链接】integration-test The repo contains test suits for system integration test 项目地址: https://gitcode.com/openeuler/integration-test 前往项目官网免费下载:…

【LINUX】驱动

【LINUX】驱动

2026/7/15 0:08:14

【LINUX驱动】【字符设备】【中断】【Platform】【网课 设备树】【GPIO】【PINCTRL】【INPUT】【IIC】【SPI】【网络驱动】【屏幕驱动】【一 设备树】【二 内核模块编译】【三 基本驱动框架】【四 Platform总线设备驱动框架】【五 驱动子系统】【六 综合】

【1982-2026】全国高精度建筑轮廓|村级精度|SHP矢量

【1982-2026】全国高精度建筑轮廓|村级精度|SHP矢量

2026/7/15 0:08:14

🔍 数据简介 本次分享1982-2026年全国村级精度建筑轮廓矢量数据,覆盖全国各省市区县,到村级别精细,为2026年最新实时采集成果,非网传仅60/77个城市的老旧数据。 数据含带高度/不带高度双版本,单体建筑边界精…

【1975-2026】全国水系水路数据|河流/水库/运河|SHP矢量

【1975-2026】全国水系水路数据|河流/水库/运河|SHP矢量

2026/7/15 0:08:14

🔍 数据简介 本次分享1975-2026年全国高精度水系水路矢量数据,覆盖全国全域,包含河流、水系、水库、运河、湿地、冰川、沟渠等全类别水文要素。 数据集包含双层矢量图层,字段分类清晰、要素齐全,支持2013-2026逐年完整…