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

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

✨核心逻辑

本题采用 二分查找(与右端点比较) 的策略:

  1. 寻找断点:旋转排序数组的特点是,最小值的左侧是一个相对较大的递增序列,最小值的右侧也是一个递增序列,但在交界处发生了数值的“断崖”。
  2. 与右端点比较:维护左指针 left 和右指针 right,每次计算中间位置 mid。通过判断 nums[mid]nums[right] 的大小关系来缩小搜索范围:
    • 如果 nums[mid] > nums[right]:说明中间位置 mid 位于最小值左侧的较大递增序列中。因此,最小值必定在 mid 的右侧,收缩左边界 left = mid + 1
    • 如果 nums[mid] <= nums[right]:说明 mid 位于最小值的右侧或者正好位于最小值的位置。因此,最小值在 mid 处或其左侧,收缩右边界 right = mid
  3. 结束条件:当 left == right 时,二者指向的位置就是最小值的索引。

🔥代码实现(含详细变量注释)

class Solution {
    public int findMin(int[] nums) {
        // left:二分查找的左边界指针,初始指向数组的第一个元素
        int left = 0;
        // right:二分查找的右边界指针,初始指向数组的最后一个元素
        int right = nums.length - 1;

        // 当左指针小于右指针时,持续进行二分查找
        while (left < right) {
            // mid:计算当前搜索区间的中间索引,使用 left + (right - left) / 2 防止溢出
            int mid = left + (right - left) / 2;
            
            // 核心判断:如果中间元素大于右边界元素,说明最小值在右半区(因为左半区是有序的且比右半区大)
            if (nums[mid] > nums[right]) {
                left = mid + 1;   // 收缩左边界到 mid 右侧
            } else {
                // 否则,说明中间元素在最小值的右侧,或者中间元素就是最小值
                right = mid;      // 收缩右边界到 mid 位置
            }
        }
        // 最终 left 和 right 相遇的位置,即最小值的索引,返回该位置的值
        return nums[left];
    }
}
  • ⏱️复杂度分析
    • 时间复杂度:O(log N),其中 N 是数组的长度。每次循环都将搜索区间缩小一半,符合题目要求的时间复杂度。

    • 空间复杂度:O(1),只使用了 left、right、mid 等常数个额外的整型变量,不需要额外的数组或递归栈空间。