二分查找篇——搜索旋转排序数组【LeetCode】两次二分查找

33. 搜索旋转排序数组

一、算法逻辑(逐步通顺讲解每一步思路)

✅ 1️⃣ 找到旋转点(即最小值下标)

使用 findMin(nums) 函数(本质是偏左二分),快速定位旋转数组的最小值下标 i,将整个数组分为两段:

  • 第一段是 nums[0:i]:比 nums[-1] 大;

  • 第二段是 nums[i:]:比 nums[-1] 小或等于。

✅ 该函数核心已分析过,详情参考

二分查找篇------寻找旋转排序数组中的最小值【LeetCode】-CSDN博客

不再赘述,其返回的是最小值的下标 i。


✅ 2️⃣ 判断目标所在区间

通过比较 target 与 nums[-1] 的大小,判断它应该位于哪一段中:

  • 如果 target > nums[-1],说明目标值在旋转点左侧,即第一段(原数组前半部分);

  • 否则,说明目标值在旋转点右侧,即第二段。


✅ 3️⃣ 二分查找目标下标

调用自定义的 lower_bound(nums, left, right, target) 方法,在对应区间内进行精确查找目标值的下标。

lower_bound 核心逻辑:
  • 搜索范围是 开区间 (left, right) ,所以初始边界可能设为 -1 或 n;

  • 使用循环不变量:

    • nums[left] < target

    • nums[right] >= target

  • 当 nums[mid] >= target,说明目标可能在左侧或就是 mid,更新 right = mid;

  • 否则目标一定在右侧,更新 left = mid;

  • 最终判断 nums[right] == target 成立时返回下标,否则返回 -1 表示未找到。


二、核心点总结

✅ 核心思想是:

将旋转排序数组分成两个单调段,然后在正确的一段中用二分查找目标。

✅ 技巧亮点包括:

  • 利用 nums[-1] 作为分界判断依据;

  • lower_bound 使用开区间写法,统一且干净;

  • 充分复用了"二分搜索 + 旋转点定位"的组合模板。

✅ 本题与 LeetCode 153 题(找最小)和 33 题(搜索目标)关联紧密,适合放在一起练习和理解。

python 复制代码
class Solution:
    # 153. 寻找旋转排序数组中的最小值(返回的是下标)
    def findMin(self, nums: List[int]) -> int:
        left, right = -1, len(nums) - 1  # 开区间 (-1, n-1)
        while left + 1 < right:  # 开区间不为空
            mid = (left + right) // 2
            if nums[mid] < nums[-1]:
                right = mid
            else:
                left = mid
        return right

    # 有序数组中找 target 的下标
    def lower_bound(self, nums: List[int], left: int, right: int, target: int) -> int:
        while left + 1 < right:  # 开区间不为空
            mid = (left + right) // 2
            # 循环不变量:
            # nums[right] >= target
            # nums[left] < target
            if nums[mid] >= target:
                right = mid  # 范围缩小到 (left, mid)
            else:
                left = mid  # 范围缩小到 (mid, right)
        return right if nums[right] == target else -1

    def search(self, nums: List[int], target: int) -> int:
        i = self.findMin(nums)
        if target > nums[-1]:  # target 在第一段
            return self.lower_bound(nums, -1, i, target)  # 开区间 (-1, i)
        # target 在第二段
        return self.lower_bound(nums, i - 1, len(nums), target)  # 开区间 (i-1, n)

三、时间复杂度分析

  • findMin 查找旋转点:O(log n)

  • lower_bound 二分搜索:O(log n)

✅ 整体时间复杂度为:O(log n)


四、空间复杂度分析

  • 使用常数个变量;

  • 无递归,无额外数组结构。

✅ 空间复杂度为:O(1)


✅ 总结一句话

本解法将旋转数组分段 + 精准定位目标值下标,结合偏左二分与逻辑清晰的 lower_bound 函数,实现了 O(log n) 时间复杂度的优雅搜索,是 LeetCode 33题的标准解法。其中的偏移下标控制和开区间技巧值得深入掌握.

相关推荐
尹人入圣6 小时前
目前热门的IP驱动产业新场景新工具
网络·python·网络协议·tcp/ip
文丑颜不良啊7 小时前
LeetCode1381~1400题目解析
java·leetcode
开开心心_Every7 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
chenbingjie_c7 小时前
C++ 多态完全指南:从虚函数重写到虚函数表原理
开发语言·c++
是main不是漫7 小时前
【双指针——移动零】数组划分类题目的入门基石
c++·算法
Nuanyt7 小时前
Agent 学习笔记(下篇三):上线工程、进阶选择与操作界面(Stage 7 / 7.5 / 8 + 延伸路线)
笔记·python·学习·memory·aiagent·harness
吴卫斌7 小时前
定投ETF实战指南(四):行业/主题ETF——定投的“进攻端“
开发语言·python·股票·量化
2601_967987378 小时前
Python——入门级(定义功能def函数)
python·函数·可变参数·默认参数·关键字参数
超级架构师8 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
深圳市快瞳科技有限公司8 小时前
野外鸟类AI识别落地实录:输入适配、结构化输出、去重聚合与置信度分流的工程实践
算法·计算机视觉·鸟类识别·鸟类ai识别·野外鸟类观测·林业调查