跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

二分查找算法详解与模板总结:从原理到变体

二分查找算法,涵盖基本原理、步骤及代码实现。介绍了基础版本及三种常见变体(查找首个/末个等于目标值、查找首个大于等于目标值)。分析了时间与空间复杂度,列举了有序数组查找、求平方根等应用场景,并总结了注意事项与易错点。最后提供通用模板及 LeetCode 实战练习题,帮助读者掌握该算法。

LinuxPan发布于 2026/3/25更新于 2026/7/2555 浏览
二分查找算法详解与模板总结:从原理到变体

二分查找算法详解

二分查找(Binary Search)是一种在有序数组中查找特定元素的高效算法。它的核心思想是分而治之,每次将搜索范围缩小一半。

基本原理

想象你在查英语字典找"apple"这个词:

  1. 翻开字典的中间
  2. 如果这一页的单词在"apple"之前,就往后翻
  3. 如果这一页的单词在"apple"之后,就往前翻
  4. 重复这个过程,直到找到"apple"

这就是二分查找的生活例子。

算法步骤

假设有一个升序数组 arr,要查找目标值 target:

  1. 初始化左指针 left = 0,右指针 right = n-1
  2. 当 left <= right 时循环:
    • 计算中间位置 mid = left + (right - left) / 2(防止整数溢出)
    • 如果 arr[mid] == target,找到目标,返回 mid
    • 如果 arr[mid] < target,说明目标在右半部分,left = mid + 1
    • 如果 arr[mid] > target,说明目标在左半部分,right = mid - 1
  3. 循环结束未找到,返回 -1

代码实现

基础版本(查找精确值)
int binarySearch(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;
    while (left <= right) {
        // 避免 (left + right) 可能溢出
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid; // 找到目标
        } else if (nums[mid] < target) {
            left = mid + 1; // 目标在右半部分
        } else {
            right = mid - 1; // 目标在左半部分
        }
    }
    return -1; // 未找到
}

时间复杂度分析

  • 时间复杂度:O(log n)
    • 每次比较后,搜索范围减半
    • 对于大小为 n 的数组,最多需要 log₂(n) 次比较
  • 空间复杂度:O(1)
    • 只需要常数级别的额外空间

二分查找的变体

1. 查找第一个等于目标的位置
int findFirst(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    int result = -1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            result = mid; // 记录当前位置
            right = mid - 1; // 继续向左查找
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return result;
}
2. 查找最后一个等于目标的位置
int findLast(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    int result = -1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            result = mid; // 记录当前位置
            left = mid + 1; // 继续向右查找
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return result;
}
3. 查找第一个大于等于目标的位置
int findFirstGreaterOrEqual(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] >= target) {
            right = mid - 1; // 虽然满足条件,但继续向左找更小的
        } else {
            left = mid + 1; // 当前太小,向右找
        }
    }
    return left; // left 就是第一个 >= target 的位置
}

常见应用场景

  1. 有序数组的查找 - 最基础的应用
  2. 求平方根 - 在 0 到 x 之间二分查找
  3. 旋转数组的查找 - 如 [4,5,6,7,0,1,2] 中查找
  4. 寻找峰值 - 在山峰数组中找到最大值
  5. 在答案空间二分 - 如"找到最小速度使得在规定时间内完成任务"

注意事项和常见错误

  1. 循环条件:left <= right vs left < right 的选择
  2. 边界更新:left = mid + 1 和 right = mid - 1 要正确
  3. 整数溢出:使用 mid = left + (right - left) / 2 而非 (left + right) / 2
  4. 数组必须有序:二分查找的前提是有序,否则结果错误
  5. 重复元素:处理重复元素时要明确需求(找第一个/最后一个)

二分查找虽然原理简单,但细节容易出错。建议多练习不同类型的题目,熟练掌握各种变体的写法。

二分算法模板总结

在这里插入图片描述

// 找左边
while (left < right) {
    int mid = left + (right - left) / 2;
    // 左边
    if (nums[mid] >= target) right = mid;
    // 右边
    else left = mid + 1;
}

// 找右边
while (left < right) {
    int mid = left + (right - left + 1) / 2;
    // 右边
    if (nums[mid] <= target) left = mid;
    // 左边
    else right = mid - 1;
}

实战练习题目(含链接)

二分查找(easy)
在排序数组中查找元素的第一个和最后一个位置(medium)
搜索插入位置(easy)
x 的平方根(easy)
山峰数组的峰顶(easy)
寻找峰值(medium)
搜索旋转排序数组中的最小值(medium)
0〜n-1 中缺失的数字(easy)

目录

  1. 二分查找算法详解
  2. 基本原理
  3. 算法步骤
  4. 代码实现
  5. 基础版本(查找精确值)
  6. 时间复杂度分析
  7. 二分查找的变体
  8. 1. 查找第一个等于目标的位置
  9. 2. 查找最后一个等于目标的位置
  10. 3. 查找第一个大于等于目标的位置
  11. 常见应用场景
  12. 注意事项和常见错误
  13. 二分算法模板总结
  14. 实战练习题目(含链接)
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 轻量级前端框架对比:Lit 与 Alpine.js 的优势与应用场景
  • Coze 基于行业文章生成思维导图工作流详解
  • Vivado 2019.2 开发环境搭建与配置指南
  • 利用 Blob 对象和 iframe 实现 PDF 跨域打印的 JavaScript 方案
  • WhisperX:单词级时间戳与说话人分离的语音转录工具
  • Windows 系统安装 Microsoft Visual C++ Build Tools 完整指南
  • 鸿蒙 ArkTS 与 Java 跨平台 TCP 通信实战
  • 2026 毕业季 AIGC 检测标准解读与应对策略
  • 飞书机器人搭建指南:基于 Webhook 实现高效消息推送
  • 2026 年主流免费 AI 写作工具测评与避坑指南
  • 基于大疆 MSDK 的无人机视觉引导自适应降落实现
  • 使用 LLaMA-Factory 微调 Qwen2.5 并转换为 GGUF 格式部署
  • STL 转 STEP 格式转换工具 stltostp 安装与使用
  • Pi0 机器人大模型在昇腾 A2 上的部署与性能测评
  • Vite 打包常见问题与解决方案详解
  • 五大经典排序算法详解:插入、希尔、冒泡、选择与堆排序
  • 微信开放官方 Bot API:ClawBot 插件技术解析与接入指南
  • MySQL 9.6.0 Windows 版安装与配置指南
  • Anaconda 环境变量配置意义及捆绑 Python 路径说明
  • openclaw新手入门指南:一文看懂环境搭建、模型配置与 WebUI 远程访问

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online