【LeetCode 153 & 173_二分查找】寻找旋转排序数组中的最小值 & 缺失的数字

算法场景

当题目中存在有序性或单调性 时,就应优先考虑二分查找:例如数组整体有序或局部有序(如旋转数组)、某个条件在区间内呈现"前真后假"或"前假后真"的分界特征、下标与数值存在固定关系(如缺失数字问题),或答案位于一个连续区间且可通过判断函数验证可行性;只要能够通过一次判断就排除一半区间,并且数据规模较大、要求 O ( l o g n ) O(logn) O(logn)复杂度,二分查找就是最合适的解法。

  • 算法场景
    • 一、寻找旋转排序数组中的最小值
      • [1.1 题目链接](#1.1 题目链接)
      • [1.2 题目描述](#1.2 题目描述)
      • [1.3 题目示例](#1.3 题目示例)
      • [1.4 算法思路](#1.4 算法思路)
      • [1.5 核心代码](#1.5 核心代码)
      • [1.6 示例测试(总代码)](#1.6 示例测试(总代码))
    • [二、缺失的数字(剑指 Offer)](#二、缺失的数字(剑指 Offer))
      • [2.1 题目链接](#2.1 题目链接)
      • [2.2 题目描述](#2.2 题目描述)
      • [2.3 题目示例](#2.3 题目示例)
      • [2.4 算法思路](#2.4 算法思路)
      • [2.5 核心代码](#2.5 核心代码)
      • [2.6 示例测试(总代码)](#2.6 示例测试(总代码))
  • 总结

一、寻找旋转排序数组中的最小值

1.1 题目链接

LeetCode153_寻找旋转排序数组中的最小值【点击进入】


1.2 题目描述

给你一个 不含重复元素 的整数数组 nums,它原本是一个升序排列的数组,但在某个未知的点上进行了旋转。

请你找出并返回数组中的 最小元素

要求时间复杂度为 O(log n)


1.3 题目示例

text 复制代码
输入:nums = [4,5,6,7,0,1,2]
输出:0
text 复制代码
输入:nums = [3,4,5,1,2]
输出:1

1.4 算法思路

这是一个典型的二分查找变形题

核心观察
  • 旋转后的数组可以看成 两段递增数组
  • 最小值一定是 旋转点
  • 我们可以将 nums[right] 作为比较基准
判断逻辑
  • nums[mid] > nums[right]
    👉 说明最小值一定在 mid 的右侧
  • 否则
    👉 最小值在 mid 或 mid 的左侧

通过不断缩小区间,最终 left == right 时,即为最小值下标。


1.5 核心代码

cpp 复制代码
class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        int x = nums[right];

        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > x)
                left = mid + 1;
            else
                right = mid;
        }
        return nums[left];
    }
};

1.6 示例测试(总代码)

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        int x = nums[right];
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > x) left = mid + 1;
            else right = mid;
        }
        return nums[left];
    }
};

int main() {
    Solution s;
    vector<int> nums = {4,5,6,7,0,1,2};
    cout << s.findMin(nums) << endl;
    return 0;
}

二、缺失的数字(剑指 Offer)

2.1 题目链接

LeetCode173_缺失的数字【点击进入】


2.2 题目描述

一个长度为 n-1 的递增数组 records,所有数字都在 [0, n-1] 范围内,且 不重复

数组中 恰好缺失一个数字,请找出这个缺失的数字。


2.3 题目示例

text 复制代码
输入:records = [0,1,2,3,4,6,7]
输出:5
text 复制代码
输入:records = [0,1,2,3]
输出:4

2.4 算法思路

这是一个非常经典的 "下标和值关系" 二分查找题

核心规律
  • 在理想情况下:records[i] == i

  • 一旦出现缺失数字:

    • 缺失数字左侧:records[i] == i
    • 缺失数字右侧:records[i] > i
二分判断
  • records[mid] == mid
    👉 缺失数字在 右侧
  • 否则
    👉 缺失数字在 左侧(包括 mid)

最终 left 即为缺失的数字。


2.5 核心代码

cpp 复制代码
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;
        }
        return left == records[left] ? left + 1 : left;
    }
};

2.6 示例测试(总代码)

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

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;
        }
        return left == records[left] ? left + 1 : left;
    }
};

int main() {
    Solution s;
    vector<int> records = {0,1,2,3,4,6,7};
    cout << s.takeAttendance(records) << endl;
    return 0;
}

总结

这两道题虽然背景不同,但本质高度相似

  • 都是 二分查找的变形

  • 核心在于:

    • 找到 单调性
    • 明确 判断条件
    • 缩小区间直到答案唯一

📌 常见二分套路总结:

  • 旋转数组 :与 nums[right] 比较
  • 缺失数字 :比较 nums[mid]mid

只要抓住"哪一侧一定有答案",二分查找就会变得非常自然。


✨ 坚持用 清晰易懂的图解 + 代码语言, 让每个知识点都 简单直观 !

🚀 个人主页不呆头 · CSDN

🌱 代码仓库不呆头 · Gitee

📌 专栏系列

💬 座右铭 : "不患无位,患所以立。"

相关推荐
Sheep Shaun2 小时前
STL:list,stack和queue
数据结构·c++·算法·链表·list
CSDN_RTKLIB2 小时前
【LeetCode 热题 HOT 100】两数之和
算法·leetcode·职场和发展
Tisfy2 小时前
LeetCode 2054.两个最好的不重叠活动:二分查找
算法·leetcode·二分查找·题解
Looooking2 小时前
Python 之通过一个天平找出9个小球中唯一重量较轻的小球
python·算法
white-persist2 小时前
【攻防世界】reverse | tt3441810 详细题解 WP
java·c语言·开发语言·数据结构·c++·算法·安全
YGGP2 小时前
【Golang】LeetCode 70. 爬楼梯
算法·leetcode
小熳芋2 小时前
组合总和- python-回溯哦&剪枝
算法·机器学习·剪枝
lxh01132 小时前
缺失的第一个正数
数据结构·算法