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

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

二分查找是处理有序或半有序数据的高效工具。解析两道典型题目:一是旋转排序数组的最小值,通过对比中点与端点值确定单调区间;二是 0 到 n-1 缺失数字,利用索引与数值的偏移规律定位断点。两者均通过二分策略将复杂度降至对数级,是掌握二分变体的关键练习。

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

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

题目描述

给定一个升序排列的数组,该数组在某个未知的下标处进行了旋转。例如 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2]。请找出其中最小的元素。

解题思路

这道题的关键在于利用数组的局部有序性。虽然整体不单调,但旋转点将数组分成了两个递增的子序列。我们可以通过比较中间元素 mid 与边界元素的关系,判断最小值位于哪一侧。

方案一:以末尾元素为基准

我们将 nums[n-1] 作为参照物。如果 nums[mid] > nums[n-1],说明 mid 落在第一个递增区间(较大的那部分),最小值一定在右侧;反之,最小值可能在左侧或就是 mid 本身。

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[nums.size() - 1]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return nums[left];
    }
};
方案二:以开头元素为基准

另一种思路是拿 nums[0] 做对比。如果 nums[mid] >= nums[0],说明 mid 还在前半段(较大值区域),需要向右收缩;否则向左收缩。注意处理数组未旋转的特殊情况。

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        while(left < right) {
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] >= nums[0]) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        // 循环结束 left 指向最大值位置,最小值在其后一位
        if(left == nums.size() - 1) {
            return nums[0];
        }
        return nums[left + 1];
    }
};

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

题目描述

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

解题思路

暴力遍历的时间复杂度是 O(n),但我们可以利用索引与数值的对应关系将其优化到 O(log n)。在未缺失数字的情况下,数组下标 i 对应的值应该等于 i。一旦遇到缺失数字,后续所有元素的值都会比下标大 1。这种'相等'与'不相等'的分界点,正是二分查找的目标。

核心逻辑
  • 若 records[mid] == mid,说明左半部分完整,缺失值在右侧。
  • 若 records[mid] != mid,说明缺失值已在左侧或当前位置。
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(mid >= records[mid]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        // 判断最后位置是否匹配
        if(left == records[left]) {
            return records[left] + 1;
        }
        return records[left] - 1;
    }
};

通过上述两个案例可以看出,二分查找不仅仅是用于查找特定值,更常用于根据某种性质划分区间。掌握这种二段性的构建方法,能解决很多看似复杂的变体问题。

目录

  1. 23. 寻找旋转排序数组中的最小值
  2. 题目描述
  3. 解题思路
  4. 方案一:以末尾元素为基准
  5. 方案二:以开头元素为基准
  6. 24. 0~n-1 中缺失的数字
  7. 题目描述
  8. 解题思路
  9. 核心逻辑

更多推荐文章

查看全部
  • Android 插件化技术:动态创建 Activity 模式详解
  • JDK 22 下载安装与 Java 开发环境配置教程
  • 利用无监督学习为大语言模型实现信息记忆与微调
  • 双向链表原理与 C 语言实现
  • C++ 类和对象:默认成员函数详解
  • Spring Boot 优雅停机演进:实现原理与最佳实践
  • GLM-4.6V-Flash-WEB 食品包装识别准确性验证
  • Flutter WalletConnect 鸿蒙适配:Web3 钱包连接与 DApp 授权实战
  • Java 面试解析:Spring Boot 与微服务架构
  • Flutter 插件适配 OpenHarmony:onMethodCall 分发与参数处理实战
  • 前端 pnpm workspace 架构详解
  • Spring MVC 响应处理:页面、数据与状态码配置详解
  • Flutter for OpenHarmony 实战:使用 Injectable 实现自动化依赖注入
  • RISC-V 处理器实战:Verilog RTL 设计与 FPGA 原型验证
  • Flutter eth_sig_util 鸿蒙适配:以太坊加密签名核心实现
  • 9 款 AI 论文写作工具横向测评与选择指南
  • Qt C++ 自定义 QDialog 及标题栏实现方案
  • 使用 VS Code + Git 高效管理 Python 学习记录
  • 2026 年 3 月全球 AI 前沿动态:模型、机器人及硬件突破
  • Milvus 向量数据库实战:Attu 可视化部署与 Python SDK 整合

相关免费在线工具

  • 加密/解密文本

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