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

二分查找算法实战:插入位置、平方根与峰顶索引

综述由AI生成通过三个经典 LeetCode 题目讲解二分查找算法的应用。包括在有序数组中搜索目标值或确定插入位置、计算整数平方根以及寻找山脉数组的峰顶索引。文章分析了暴力解法的局限性,详细阐述了如何利用二分查找将时间复杂度优化至 O(log n),并提供了 C++ 代码实现及关键逻辑解析。

MongoKing发布于 2026/3/28更新于 2026/6/127 浏览
二分查找算法实战:插入位置、平方根与峰顶索引

一、搜索插入位置

题目解析

在这里插入图片描述

这道题,给定一个数组 nums 和一个目标值 target,让我们在数组 nums 中找到目标值;如果目标值存在就返回它的下标,如果不存在就返回数 target 被顺序插入的位置下标。

算法思路

这道题,我们可以使用暴力查找,时间复杂度是 O(n)。

从左到右遍历数组,找到值大于等于 target 的起始位置(如果 target 不存在,那要找的就是 target 顺序插入的位置)

题目要求我们要使用时间复杂度为 O(log n) 的算法来解决,暴力解法的时间复杂度为 O(n)(暴力解法虽然可以通过这道题)

思考以下:数组 nums 是有序的,且我们要找的是 >=target 的起始位置,那也就是大于等于 target 区间的左端点;

我们再随机挑选一个位置 i,区间 [0,i-1] 中的数都是小于 i 位置的数;区间 [i+1 , n] 中的数都是大于 i 位置的数的。

那我们就可以使用二分查找

首先定义 left 和 right 指向数组的起始位置和结束位置。取 mid = left + (right - left)/2 比较 mid 位置的值和 target 如果 nums[mid] > target,就去左边区间查找;right = mid - 1。如果 nums[mid] < target,就去右边区间查找;left = mid + 1。如果 nums[mid] == target,就查找到了 target,就返回当前位置下标即可。这里因为我们要查找的是 >=target 区间的左端点,所以在遍历结束后,l 指向的就是 target 顺序排序的插入位置。

代码实现

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int l = 0, r = nums.size() - 1;
        while (l <= r) {
            int mid = (l + r) / 2;
            if (nums[mid] < target) l = mid + 1;
            else if (nums[mid] > target) r = mid - 1;
            else return mid;
        }
        return l;
    }
};

二、x 的平方根

题目解析

在这里插入图片描述

这道题,给定一个非负整数 x,让我们计算它的算术平方根。

注意:我们返回类型是一个整数,结果只保留整数部分,小数部分要舍去(也就是向下取整)

算法思路

对于这道题,暴力解法:

我们从 0 开始向后遍历,依次判断 i 是不是我们要找的 x 是算术平方根;

这里可以从 x 开始向后遍历,查找到第一个 i 的平方小于等于 x 的位置。

暴力解法遍历的区间是 [1 , x],我们遍历过程中要判断 i 的平方是否等于 x(或者大于)

但是我们思考一下 [1 , x] 区间内数的平方它是递增的;

当我们遍历一个位置 i 时,那 [1, i-1] 区间内任意一个数的平方都小于 i 的平方;区间 [i+1 , x] 内的任意一个数的平方都是大于 i 的平方的。

所以我们就可以使用二分查找来查找平方 <=x 区间的左端点。

首先定义 left,right(初始值为 0 和 x),然后取 mid = left +(right - left + 1)/2 如果 mid*mid < x:此时左边区间数的平方都是小于 x,肯定不会是最终结果;left = mid。如果 mid*mid > x:此时右边区间数的平方都是大于 x,mid 平方也是大于 x 的,肯定也不会是最终结果;right = mid - 1。如果 mid*mid == x:此时就找到了 x 的算数平方根,返回结果即可。

最后遍历结束 left 和 right 指向位置就是最终结果。

在这里插入图片描述

暴力解法遍历的区间是 [1 , x],我们遍历过程中要判断 i 的平方是否等于 x(或者大于)

代码实现

class Solution {
public:
    int mySqrt(int x) {
        long long left = 0, right = x;
        while (left < right) {
            long long mid = left + (right - left + 1) / 2;
            long long sum = mid * mid;
            if (sum > x) right = mid - 1;
            else if (sum < x) left = mid;
            else return mid;
        }
        return left;
    }
};

三、山脉数组的峰顶索引

题目解析

在这里插入图片描述

对于这道题,给定一个数组 nums,数组中的数据大小是山峰形状的(也就是先递增,然后再递减)

现在我们要找到,山峰峰顶的索引值;也就是先递增再下降的转折点。

算法思路

暴力解法:

遍历数组,找到呈下降趋势的起始位置。

简单来说就是遍历数组,如果当前位置是小于下一个位置的值,也就是下降趋势就继续遍历;

如果当前位置是大于下一个位置的值的,也就是上升趋势就返回结果即可。

题目中说,数组中的值是先递增到一个值再递减的,那也就是说我们遍历一个位置 i 时,只存在以下两种情况:

  • 递增:nums[i] > nums[i+1]
  • 递减:nums[i] < nums[i+1]

所以我们遍历一个位置 i 时:如果当前是递增趋势 (nums[i] < nums[i+1]),那区间 [l,i] 就是递减的,我们要找的最终结果肯定是在区间 [i+1, r] 中的;如果当前是递减趋势,也就是 nums[i] > nums[i+1],那区间 [i+1, r] 就是递减的,而 i 位置也可能是我们最终要找的结果,所以我们要找的最终结果肯定是在区间 [l,i] 中的。

所以这道题我们就可以使用二分查找来搜索山峰的峰顶位置。

二分查找

这里我们通过上面分析我们可以发现,我们可以将区间分成两部分,一部分是不满足条件的,一部分可能满足条件的;

而这里我们要找的是递减区间的左端点。

首先定义 left,right(初始值为 0 和 n-1),然后取 mid = left +(right - left)/2 如果 nums[mid] < nums[mid+1]:此时区间 [left , mid] 是不满足条件的,就要去区间 [mid+1 , right] 中查找最终结果。如果 nums[mid] > nums[mid+1]:此时区间 [mid+1 , right] 是不满足条件的,就要去区间 [left , mid] 中查找最终结果。

最后遍历结束,left 和 right 指向的就是最终结果。

代码实现

class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) {
        int l = 0, r = arr.size() - 1;
        while (l < r) {
            int mid = (l + r) / 2;
            if (arr[mid] > arr[mid + 1]) r = mid;
            else l = mid + 1;
        }
        return l;
    }
};

目录

  1. 一、搜索插入位置
  2. 题目解析
  3. 算法思路
  4. 代码实现
  5. 二、x 的平方根
  6. 题目解析
  7. 算法思路
  8. 代码实现
  9. 三、山脉数组的峰顶索引
  10. 题目解析
  11. 算法思路
  12. 代码实现
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • C++ 标准库容器适配器:Stack、Queue 与 Priority Queue 详解
  • AI 辅助编程工具:GitHub Copilot 安装与使用指南
  • 2025 年 12 月 GESP CCF 编程能力等级认证 C++ 六级真题
  • OpenClaw 开源 AI 项目实战指南:部署、技能与多端接入
  • 流处理与 RAG 驱动的 Python 智能 ETL 框架:构建智能数据管道 (上)
  • 商汤开源 SenseNova-MARS:多模态搜索推理模型解析
  • 使用 CopilotKit 快速为前端集成 AI 助手实战指南
  • Docker Compose 实战:一键部署 Web、数据库与缓存微服务环境
  • 基于 Python Flask + Vue3 的学生信息管理系统设计与实现
  • AI 数据标注平台的选型与实践:效率提升背后的技术逻辑
  • 从 vw/vh 到 clamp():前端响应式设计的痛点与进化
  • OpenClaw 多智能体路由与飞书多机器人配置指南
  • Odoo 免费开源 CRM 客户关系管理系统介绍
  • Spring Cloud 微服务架构概述与工程搭建
  • Spring Boot 日志使用与配置
  • 本地部署 OCR 文字检测系统:ResNet18 WebUI 一键启动指南
  • LeetCode 链表经典题目解析:移除、反转、中间节点与回文结构
  • AI 智能体 Skills 驱动开发:从使用到项目实战详解
  • Linux 系统编程实践:手动实现 Shell
  • MySQL 数据库基础操作:查看、创建、编码与备份

相关免费在线工具

  • 加密/解密文本

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