LeetCode 154. 寻找旋转排序数组中的最小值 II
题目描述


题意分析
一个非递减数组经过旋转后,找到其中的最小值。数组非空,允许重复元素,也可能旋转后仍与原数组相同;只需返回最小值,不要求定位它第一次出现的下标。
旋转会把有序数组拆成前后两段,各段内部仍非递减,前段的值不小于后段。没有重复值时通常可以直接判断最小值在哪一侧;有重复值时,相等比较可能隐藏分界,不能每轮都强行排除一半。
解法:二分查找
核心思路
[!blue]
用闭区间
[left, right]保存候选范围,始终保证其中至少还有一次全局最小值。每轮比较nums[mid]与当前右端值,根据大小关系决定可以安全排除的部分。若
nums[mid] > nums[right],从中点到右端之间一定跨过了旋转后的下降位置,否则非递减顺序不可能出现前大后小。中点仍在较大的前段,最小值在它右边的后段,因此连同中点一起排除,令left = mid + 1。若
nums[mid] < nums[right],中点到右端不可能跨过从较大前段到较小后段的分界,这一段保持非递减。中点后面的值不会比中点更小,因此不必继续保留它们;但中点自身可能就是最小值,令right = mid,将它留在候选区间内。若两者相等,最小值可能在中点的任意一侧,无法判断应该保留哪一半。不过右端仍可以删除:若它不是最小值,删除无影响;若它恰好是最小值,中点还保留着相同值。由于循环中
mid < right,执行right--不会同时删掉这个副本。三种分支都缩小范围,而且不会丢掉全部最小值候选。最终
left == right,只剩的位置就必然存放最小值。重复值很多时可能连续执行单步缩小,这是重复信息不足带来的最坏情况。
解题步骤
- 初始化
left = 0、right = nums.length - 1。- 只要
left < right,计算中点mid。- 中点值大于右端值时,令
left = mid + 1。- 中点值小于右端值时,令
right = mid,保留可能为答案的中点。- 两者相等时,只令
right--,删除一个有副本的候选。- 区间收敛后返回
nums[left]。
代码实现
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 if (nums[mid] < nums[right]) {
right = mid;
} else {
// 重复值无法判断方向,安全丢弃一个右端点。
right--;
}
}
return nums[left];
}
}
func findMin(nums []int) int {
left := 0
right := len(nums) - 1
for left < right {
mid := left + (right-left)/2
if nums[mid] > nums[right] {
left = mid + 1
} else if nums[mid] < nums[right] {
right = mid
} else {
// 相等时无法排除 mid,只缩小 right。
right--
}
}
return nums[left]
}
复杂度分析
- 时间复杂度:最坏 $O(n)$,元素全部相等时每轮只能删除一个右端点;能持续确定方向时为 $O(\log n)$。
- 空间复杂度:$O(1)$,只使用固定数量的下标变量。
关键点总结
[!green]
- 二分依据是候选答案具有可排除的一侧,而不是数组必须整体有序。
nums[mid] < nums[right]时必须保留mid,所以更新为right = mid。- 相等时没有方向信息;
right--的正确性来自区间内存在同值副本。
易错点总结
[!yellow]
- 相等时直接舍弃半个区间:相等比较没有提供最小值的方向信息,可能删掉唯一的更小值。
- 小于分支写成
right = mid - 1:中点本身可能是答案,应当保留。- 相等时随意删除左端:相等的是中点与右端,安全副本只证明右端可删,不能据此删除左端。
- 只寻找严格下降位置:完全有序、全相等或单元素数组未必存在下降位置,但仍有最小值。
- 始终声称对数时间:遇到重复值时只减少一个候选,最坏时间会退化为线性。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 153. 寻找旋转排序数组中的最小值 | 中等 | 不含重复值时每次可确定保留的一半,本题遇相等需额外缩小无信息边界。 |
| 81. 搜索旋转排序数组 II | 中等 | 同样处理重复旋转数组,原题查找目标,本题定位最小元素。 |
| 33. 搜索旋转排序数组 | 中等 | 利用旋转数组中仍有序的一半排除搜索区间;本题重复值相等时逐步缩小不确定区间,该题元素互异时定位目标下标。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!