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

二分查找实战:旋转数组最小值与缺失数字

二分查找在特定场景下的两种典型应用。针对旋转排序数组,利用右端点作为基准判断区间单调性,快速定位最小值;对于有序数组中的缺失数字,依据元素值与下标的对应关系构建二段性,通过二分逼近首个不匹配位置。两者均将时间复杂度优化至 O(logN),避免线性遍历。

1739658202发布于 2026/3/29更新于 2026/10/3077 浏览
二分查找实战:旋转数组最小值与缺失数字

23. 寻找旋转排序数组中的最小值

题目描述

假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,[0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2]。请找出其中最小的元素。

解题核心

这道题的关键在于利用数组的'二段性'。虽然整体不是有序的,但我们可以观察到:

  1. 如果我们将数组分为两部分,一部分是严格递增的,另一部分也是严格递增的(只是数值较小)。
  2. 最小值一定位于那个'断点'处。
  3. 通过比较中间值 mid 和右端点 right 的值,我们可以判断 mid 落在哪一段。

具体逻辑:

  • 若 nums[mid] > nums[right],说明最小值在 mid 右侧(因为 mid 处于较大的前半段),此时 left = mid + 1。
  • 若 nums[mid] <= nums[right],说明最小值在 mid 左侧或就是 mid 本身(mid 处于较小的后半段),此时 right = mid。

当 left == right 时,循环结束,该位置即为最小值。

C++ 参考实现

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        
        while (left < right) {
            int mid = left + (right - left) / 2;
            // 以右端点为基准进行比较
            if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return nums[left];
    }
};

注意:这里选择 nums[right] 作为参照物比 nums[0] 更稳健,避免了处理数组完全有序时的特殊分支判断,代码更简洁。


24. 0~n-1 中缺失的数字

题目描述

一个长度为 n-1 的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围 0~n-1 之内。在范围 0~n-1 内的 n 个数字中有且只有一个数字不在该数组中,请找出这个数字。

解题核心

这道题同样可以利用二分查找将时间复杂度优化到 O(logN)。观察数组下标与数值的对应关系:

  • 在缺失数字出现之前,所有元素都满足 nums[i] == i。
  • 在缺失数字出现之后,由于前面的数字少了一个,后续元素都会发生偏移,满足 nums[i] != i。

这种'前真后假'的特性构成了典型的二段性,非常适合二分查找。

具体逻辑:

  • 计算中间索引 mid。
  • 若 nums[mid] == mid,说明缺失的数字在右侧,left = mid + 1。
  • 若 nums[mid] != mid,说明缺失的数字在左侧(包含 mid),right = mid。

循环结束后,left 指向第一个不满足 nums[i] == i 的位置,即缺失的数字。

C++ 参考实现

class Solution {
public:
    int takeAttendance(vector<int>& records) {
        int left = 0;
        int right = records.size() - 1;
        
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (records[mid] == mid) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        
        // 循环结束时 left 指向第一个不匹配的位置
        // 如果整个数组都匹配(理论上不会发生,除非数据异常),则返回 n
        return left;
    }
};

总结

这两道题展示了二分查找在不同场景下的变体应用:

  1. 旋转数组:通过比较中间值与边界值来判断单调区间,从而收缩搜索范围。
  2. 缺失数字:利用索引与数值的等差关系构建二段性,定位断点。

掌握这些模式后,遇到类似的'局部有序'或'索引偏移'问题,就能迅速联想到二分查找的解法。

目录

  1. 23. 寻找旋转排序数组中的最小值
  2. 题目描述
  3. 解题核心
  4. C++ 参考实现
  5. 24. 0~n-1 中缺失的数字
  6. 题目描述
  7. 解题核心
  8. C++ 参考实现
  9. 总结

更多推荐文章

查看全部
  • JavaWeb 数据交换与异步请求:JSON 和 Ajax 详解
  • Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦
  • 用 Python 把 CSV 导入 Neo4j 的实操记录
  • 基于微服务架构的智能家居物联网平台实现
  • 数据库索引类型与结构详解
  • Antigravity Tools:用 Rust+Tauri 构建本地化 AI 调度网关
  • Python 变量与基础数据类型详解
  • 医疗连续体机器人模块化控制界面设计与 Python 库应用研究
  • 利用 JuiceSSH 和 cpolar 实现手机远程管理 Linux 服务器
  • Kubernetes 核心技术与实践文章精选
  • 近五年体内微纳机器人肿瘤精准治疗综述:聚焦胶质母细胞瘤
  • CSS 盒子模型详解:边框、内边距与外边距
  • 利用 Anthropic frontend-design Skill 提升大模型前端设计审美
  • ComfyUI 集成 Stable Diffusion 3.5 FP8 模型与性能优化
  • Ubuntu 环境下 llama.cpp 编译与性能调优指南
  • 基于腾讯混元 3D 大模型实现静态图片转 3D 模型教程
  • Stable Diffusion 模型下载器使用教程
  • GitHub 访问加速:本地 hosts 配置与 DNS 刷新指南
  • OpenClaw 多机器人多 Agent 模式解析
  • C++ 图论实战:深入理解三种最短路径算法

相关免费在线工具

  • 加密/解密文本

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