【LeetCode】153. 寻找旋转排序数组中的最小值
解题思路
本题要求在旋转排序数组中寻找最小元素,数组元素互不相同且满足旋转数组的特性(由两个有序子数组组成,前子数组所有元素大于后子数组所有元素)。核心思路是利用二分查找,通过比较中间元素与右边界元素的值,逐步缩小搜索范围,最终定位到最小元素。
关键特性
- 旋转数组结构:旋转后的数组由两个有序子数组组成,前子数组所有元素大于后子数组所有元素。
- 最小元素位置:最小元素位于后子数组的开头,即旋转点。
- 时间复杂度要求:必须设计 O(log n) 的算法,因此需用二分查找。
关键步骤
- 初始化指针:设置左指针
left = 0,右指针right = len(nums)-1。 - 二分循环:
- 计算中点:
mid = left + (right - left) / 2(防溢出)。 - 比较中点与右边界:
- 若
nums[mid] > nums[right]:说明中点在前子数组,最小元素在右侧(mid+1到right),更新left = mid + 1。 - 若
nums[mid] < nums[right]:说明中点在后子数组,最小元素在左侧(left到mid),更新right = mid。
- 若
- 计算中点:
- 终止条件:当
left == right时,找到最小元素nums[left]。
为何比较
nums[mid]和nums[right]?
因为旋转数组中,前子数组元素均大于后子数组元素。通过比较中点与右边界,可明确判断中点所在子数组,从而缩小搜索范围。
代码实现
代码解析
- 循环条件:
left < right确保在指针相遇时终止循环。 - 中点计算:
left + (right-left)/2避免大数溢出。 - 分支逻辑:
nums[mid] > nums[right]→ 中点在前子数组 → 最小元素在mid右侧。nums[mid] < nums[right]→ 中点在后子数组 → 最小元素在mid左侧(含mid)。
- 返回值:最终
left指向最小元素。
示例测试
复杂度分析
| 指标 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(log n) | 每次循环将搜索范围减半,最坏情况需 log n 次比较 |
| 空间复杂度 | O(1) | 仅使用常数级别的额外空间 |
关键点总结
-
二分查找的适用性:
利用旋转数组的局部有序性,通过比较中点与右边界元素,将时间复杂度优化至 O(log n)。 -
指针更新逻辑:
-
left = mid + 1:当nums[mid] > nums[right]时,mid一定不是最小元素。 -
right = mid:当nums[mid] < nums[right]时,mid可能是最小元素,故保留。
-
-
终止条件:
循环终止时left == right,指向最小元素,无需额外判断。 -
边界处理:
- 单元素数组直接返回。
- 完全升序数组(无旋转)通过
nums[mid] < nums[right]分支正确处理。
为何不用比较左边界?
比较左边界(如nums[mid]与nums[left])无法明确区分中点所在子数组(例如旋转点左侧可能连续递增),而比较右边界可避免此问题。

浙公网安备 33010602011771号