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

二分查找算法简介及在排序数组中查找元素的首尾位置

二分查找算法原理及其在有序数组中的应用。涵盖基础二分查找寻找目标值索引,以及进阶版查找目标值首次和末次出现位置。通过左右边界收缩策略,实现 O(log n) 时间复杂度。提供 C++ 代码模板及详细逻辑分析,适用于解决排序数组中的定位问题。

lzdxwyh发布于 2026/3/30更新于 2026/6/621 浏览
二分查找算法简介及在排序数组中查找元素的首尾位置

二分查找算法简介

二分查找(Binary Search),也称为折半查找,是一种高效的有序数组查找算法。其核心思想是通过不断将搜索区间减半,快速缩小目标值的可能范围,最终找到目标值或确定其不存在。该算法的时间复杂度为 O(log n),远优于顺序查找的 O(n),在处理大规模有序数据时优势显著。

17. 二分查找

题目描述: 给定一个升序排列的整数数组 nums 和一个目标值 target,找出目标值在数组中的索引。如果不存在,返回 -1。

解法:
算法流程:
  1. 定义 left、right 指针,分别指向数组的左右区间。
  2. 找到待查找区间的中间点 mid,找到之后分三种情况讨论:
    • arr[mid] == target:说明正好找到,返回 mid 的值;
    • arr[mid] > target:说明 [mid, right] 这段区间都是大于 target 的。因此舍去右边区间,往左边 [left, mid-1] 的区间继续查找,即让 right = mid - 1,然后重复步骤 2;
    • arr[mid] < target:说明 [left, mid] 这段区间的值都是小于 target 的。因此舍去左边区间,在右边 [mid+1, right] 区间继续查找,即让 left = mid + 1,然后重复步骤 2。
  3. 当 left 与 right 错开时,说明整个区间都没有这个数,返回 -1。
C++ 算法代码:
class Solution {
public:
    int search(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)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;
            else
                return mid;
        }
        return -1;
    }
};
二分查找算法模板:
int left = 0, right = nums.size() - 1;
while (left <= right) {
    int mid = left + (right - left) / 2; // 防止数据溢出
    if (条件判断) left = mid + 1;
    else if (条件判断) right = mid - 1;
    else return 结果;
}

18. 在排序数组中查找元素的第一个和最后一个位置

题目描述: 给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值,返回 [-1, -1]。

解法:

算法思路: 使用二分思想,根据数据的性质,在某种判断条件下将区间一分为二,然后舍去其中一个区间,再在另一个区间内查找。

方便叙述,用 x 表示该元素,resLeft 表示左边界,resRight 表示右边界。

寻找左边界思路: 寻找左边界时需要注意以左边界划分的两个区间的特点:

  • 左边区间 [left, resLeft - 1] 都是小于 x 的;
  • 右边区间(包括左边界)[resLeft, right] 都是大于等于 x 的。

关于 mid 的落点,分为两种情况:

  • 当 mid 落在 [left, resLeft - 1] 区间的时候,也就是 arr[mid] < target。说明 [left, mid] 都是可以舍去的,此时更新 left 到 mid + 1 的位置,继续在 [mid + 1, right] 上寻找左边界;
  • 当 mid 落在 [resLeft, right] 的区间的时候,也就是 arr[mid] >= target。说明 [mid + 1, right](因为 mid 可能是最终结果,不能舍去)是可以舍去的,此时更新 right 到 mid 的位置,继续在 [left, mid] 上寻找左边界。

由此,就可以通过二分来快速寻找左边界。 注意:这里找中间元素需要向下取整。因为后续移动左右指针的时候,左指针 left = mid + 1 会向后移动,而右指针 right = mid 可能会原地踏步(例如剩下 1, 2 两个元素,left=1, right=2, mid=2。若向上取整则 mid=2,更新后 left,right,mid 不变,陷入死循环)。因此当 right = mid 时,要向下取整。

寻找右边界思路: 寻找右边界时注意到右边界的特点:

  • 左边区间(包括右边界)[left, resRight] 都是小于等于 x 的;
  • 右边区间 [resRight + 1, right] 都是大于 x 的。

关于 mid 的落点,分为两种情况:

  • 当 mid 落在 [left, resRight] 区间的时候,说明 [left, mid - 1](mid 不可以舍去,因为有可能是最终结果)都是可以舍去的,此时更新 left 到 mid 的位置;
  • 当 mid 落在 [resRight + 1, right] 的区间的时候,说明 [mid, right] 内的元素是可以舍去的,此时更新 right 到 mid - 1 的位置。

由此,就可以通过二分来快速寻找右边界。 注意:这里找中间元素需要向上取整。因为后续移动左右指针的时候,左指针 left = mid 可能会原地踏步(例如剩下 1, 2 两个元素,left=1, right=2, mid=1。若向下取整则 mid=1,更新后 left,right,mid 不变,陷入死循环)。因此当 left = mid 时,要向上取整。

C++ 算法代码:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int begin = 0, end = 0, mid = 0;
        if (nums.empty()) {
            return {-1, -1};
        }
        // 1. 查找区间左端点
        int left = 0, right = nums.size() - 1;
        while (left < right) {
            mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid + 1;
            else
                right = mid;
        }
        if (nums[left] == target)
            begin = left;
        else
            return {-1, -1};

        // 2. 查找区间右端点
        left = 0, right = nums.size() - 1;
        while (left < right) {
            mid = left + (right - left + 1) / 2; // 向上取整
            if (nums[mid] <= target)
                left = mid;
            else
                right = mid - 1;
        }
        if (nums[right] == target)
            end = right;
        else
            return {-1, -1};

        return {begin, end};
    }
};

总结

本文讲解了二分查找的基础应用及变体,重点在于处理边界条件和避免死循环。掌握左右边界的收缩逻辑是解决此类问题的关键。

目录

  1. 二分查找算法简介
  2. 17. 二分查找
  3. 解法:
  4. 算法流程:
  5. C++ 算法代码:
  6. 二分查找算法模板:
  7. 18. 在排序数组中查找元素的第一个和最后一个位置
  8. 解法:
  9. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 基于 Python 和 Selenium 的自动化抢票脚本实现
  • AI 大模型工程师成长路径:从零基础到就业
  • Graylog 开源日志管理平台:从零部署到高级应用
  • 延迟渲染中的 C++ 实现要点与性能权衡
  • Java 双向链表实现与 LinkedList 源码解析
  • 融合条件扩散与图学习的 EEG 信号重建与认知负荷识别
  • Spring AI 集成 PGvector:向量存储与相似性搜索实战
  • 基于闲置 Mac Mini 部署 OpenClaw 打造私人金融 AI 助手
  • 基于 Java+SpringBoot+SSM 的音乐分享与交流平台设计与实现
  • 金仓数据库 KingbaseES:多模融合架构与全场景替代方案
  • AI 写作工具全流程应用指南:从开题到答辩
  • 旋转位置编码 RoPE:从 2D 到 nD 的扩展与原理
  • Qwen3 与 Qwen Agent 智能体开发实战:接入 MCP 工具
  • 基于 Llama-Factory 微调中文小说续写模型实践
  • Python 实现 AI 文档总结、代码生成与资料检索工具
  • 飞书机器人联动 Claude Code:打造移动端 AI 编程助手
  • Nmap 基础教程:端口扫描与安全检测指南
  • FuseLLM:基于知识融合的大模型集成方法
  • 钉钉 Webhook 机器人集成与@用户功能指南
  • Flutter 框架现状分析与 Dart 语言核心学习指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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