LeetCode 153. 寻找旋转排序数组中的最小值:二分查找法详解及高频疑问解析

文章目录

    • 问题描述
    • 算法思路:二分查找法
    • 代码实现
    • 代码解释
    • 高频疑问解答
      • [1. 为什么循环条件是 `left < right` 而不是 `left <= right`?](#1. 为什么循环条件是 left < right 而不是 left <= right?)
      • [2. 为什么比较 `numsmid > numsright` 而不是 `numsleft <= numsmid`?](#2. 为什么比较 nums[mid] > nums[right] 而不是 nums[left] <= nums[mid]?)
      • [3. 为什么 `right = mid` 而不是 `right = mid - 1`?](#3. 为什么 right = mid 而不是 right = mid - 1?)
    • 总结

问题描述

已知一个长度为 n 的旋转排序数组 (例如原数组 [0,1,2,4,5,6,7] 旋转后可能变为 [4,5,6,7,0,1,2]),要求以 O(log n) 的时间复杂度找到数组中的最小值。


算法思路:二分查找法

旋转排序数组的特点是部分有序 ,可以通过二分查找法快速定位最小值。核心思路是通过比较中间元素与右边界元素,逐步缩小搜索范围。

关键步骤

  1. 初始化指针 :左指针 left = 0,右指针 right = nums.length - 1。
  2. 循环条件 :当 left < right 时继续循环。
  3. 计算中间位置 :mid = left + (right - left) / 2(避免整数溢出)。
  4. 比较与调整指针 :
    • 若 nums[mid] > nums[right],说明最小值在右半段,调整左指针 left = mid + 1。
    • 否则,最小值在左半段或当前 mid 位置,调整右指针 right = mid。
  5. 终止条件 :当 left == right 时,找到最小值。

代码实现

java 复制代码
class Solution {
    public int findMin(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return nums[left];
    }
}

代码解释

代码片段 说明
int left = 0 初始化左指针指向数组起始位置。
int right = nums.length - 1 初始化右指针指向数组末尾位置。
mid = left + (right - left) / 2 计算中间位置,避免直接相加导致的整数溢出。
nums[mid] > nums[right] 比较中间元素与右边界元素,决定搜索方向。
left = mid + 1 中间元素大于右边界,最小值在右侧,左指针右移。
right = mid 中间元素小于等于右边界,最小值在左侧或当前 mid 位置,右指针左移。
return nums[left] 循环结束时 left 和 right 重合,指向最小值。

高频疑问解答

1. 为什么循环条件是 left < right 而不是 left <= right?

  • 核心逻辑 :当 left == right 时,已经锁定唯一可能的最小值位置,无需继续循环。
  • 示例分析 :
    • 若数组只有一个元素(如 [3]),直接返回 nums[0]。
    • 若数组未旋转(如 [1,2,3,4]),最终 left 和 right 会收敛到 0。
  • 风险提示 :若使用 left <= right,当 left == right 时,循环内会计算一次 mid = left,但此时已找到结果,多余的循环可能引发逻辑错误。

2. 为什么比较 nums[mid] > nums[right] 而不是 nums[left] <= nums[mid]?

  • 核心逻辑:旋转数组的最小值一定在"右半段"或"左半段"的分界点,直接比较中间元素和右边界可精准定位方向。
  • 示例分析 :
    • 情况1 :nums[mid] > nums[right](如 [4,5,6,1,2] 中 mid=6,right=2),说明最小值在右半段。
    • 情况2 :nums[mid] <= nums[right](如 [5,1,2,3,4] 中 mid=2,right=4),说明最小值在左半段或 mid 处。
  • 对比策略 :若比较 nums[left] <= nums[mid],可能误判无序区间(如 [3,1,2] 中 mid=1 时,nums[left]=3 <= nums[mid]=1 不成立)。

3. 为什么 right = mid 而不是 right = mid - 1?

  • 核心逻辑 :当 nums[mid] <= nums[right] 时,mid 可能是最小值,不能跳过。
  • 示例分析 :
    • 正确示例 :[4,5,1,2,3] 中 mid=1,nums[mid]=1 是实际最小值,若 right = mid-1 会跳过正确值。
    • 错误风险 :在 [3,1,2] 中若 right = mid-1,mid=1 时 right 变为 0,导致返回错误值 nums[0]=3。

总结

  1. 时间复杂度 :二分查找法的时间复杂度为 O(log n),空间复杂度为 O(1)。
  2. 适用场景:适用于所有旋转排序数组(包括未旋转的情况)。
  3. 关键点:通过比较中间元素与右边界元素,确保每次循环将搜索区间缩小一半。
  4. 注意事项:需处理边界条件(如数组未旋转或只有一个元素)。

通过本文的分析,可以深入理解二分查找法在旋转排序数组中的应用,并掌握高频疑问的核心逻辑。

相关推荐
吞下星星的少年·-·1 小时前
Div.3 CF 1131A题(排序,模拟)
算法·模拟·排序
圣保罗的大教堂2 小时前
leetcode 453. 最小操作次数使数组元素相等 中等
leetcode
aichitang20242 小时前
代数拓扑学与现代前沿视角
考研·算法·数学建模·ai·拓扑学·高考
二本咕咕-机械转码2 小时前
FreeRTOS深入解析(一)_链表与并发保护——哨兵循环链表、排序键游标、临界区与关调度
单片机·算法·链表
-银雾鸢尾-2 小时前
两数之和-C++实现
c++·算法
j7~2 小时前
【动态规划算法专题】动态规划五部曲实战:泰波那契数、三步问题、最小花费爬楼梯
c++·算法·动态规划·数据结构与算法
倍利福猎头公司官方账号3 小时前
大企业HR如何向猎头公司清晰传达AI岗位的技术需求?
人工智能·算法·机器人·求职招聘·业界资讯
揽星河..3 小时前
【C++】类和对象
c++·算法
D e re k ZH4 小时前
C++ 并发、未定义行为与工程化难点(No 3)
数据结构·c++·算法·面试