寻找旋转排序数组中的最小值 II
难度:
标签:
题目描述
已知一个长度为
n
的数组,预先按照升序排列,经由 1
到 n
次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7]
在变化后可能得到:
- 若旋转
4
次,则可以得到[4,5,6,7,0,1,4]
- 若旋转
7
次,则可以得到[0,1,4,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]]
旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
给你一个可能存在 重复 元素值的数组 nums
,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须尽可能减少整个过程的操作步骤。
示例 1:
输入:nums = [1,3,5] 输出:1
示例 2:
输入:nums = [2,2,2,0,1] 输出:0
提示:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums
原来是一个升序排序的数组,并进行了1
至n
次旋转
进阶:这道题与 寻找旋转排序数组中的最小值 类似,但 nums
可能包含重复元素。允许重复会影响算法的时间复杂度吗?会如何影响,为什么?
代码结果
运行时间: 19 ms, 内存: 16.5 MB
/*
* Problem: Given a rotated sorted array that may contain duplicates, find the minimum element.
* Approach: Using Java Stream API to find the minimum element in the array. This approach is less efficient than binary search,
* but demonstrates how to use Streams for such problems.
*/
import java.util.Arrays;
public class Solution {
public int findMin(int[] nums) {
return Arrays.stream(nums).min().getAsInt();
}
}
解释
方法:
这个题解使用了二分查找的思路。首先定义左右指针 l 和 r,分别指向数组的两端。然后进入循环,每次计算中点 m,比较中点元素 nums[m] 和右端点元素 nums[r] 的大小关系。如果 nums[m] > nums[r],说明最小值在右半部分,更新 l = m;如果 nums[m] < nums[r],说明最小值在左半部分(包括 m),更新 r = m;如果相等,无法判断最小值在哪个部分,但可以确定 nums[r] 不是最小值(因为有重复元素),所以可以缩小右边界,更新 r -= 1。最后循环结束时,r 指向的就是最小值的位置。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在二分查找中,为什么选择比较中点元素 nums[m] 和右端点元素 nums[r] 而不是左端点元素 nums[l]?
▷🦆
当 nums[m] == nums[r] 时,我们只是简单地执行 r -= 1,这种处理方式是否可能跳过数组中真正的最小值?
▷🦆
在二分查找的过程中,l 初始化为 -1 而不是 0,这种初始化方式有什么特殊的考虑或优势吗?
▷🦆
代码中使用了 ans = inf,但似乎并没有在后续代码中使用这个变量。这是代码中的一个错误还是有其他意图?
▷相关问题
寻找旋转排序数组中的最小值
已知一个长度为
n
的数组,预先按照升序排列,经由 1
到 n
次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7]
在变化后可能得到:
- 若旋转
4
次,则可以得到[4,5,6,7,0,1,2]
- 若旋转
7
次,则可以得到[0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]]
旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
给你一个元素值 互不相同 的数组 nums
,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n)
的算法解决此问题。
示例 1:
输入:nums = [3,4,5,1,2] 输出:1 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:
输入:nums = [4,5,6,7,0,1,2] 输出:0 解释:原数组为 [0,1,2,4,5,6,7] ,旋转 3 次得到输入数组。
示例 3:
输入:nums = [11,13,15,17] 输出:11 解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。
提示:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums
中的所有整数 互不相同nums
原来是一个升序排序的数组,并进行了1
至n
次旋转