Find Minimum in Rotated Sorted Array II (H)
题目
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7]
might become [4,5,6,7,0,1,2]
).
Find the minimum element.
The array may contain duplicates.
Example 1:
Input: [1,3,5]
Output: 1
Example 2:
Input: [2,2,2,0,1]
Output: 0
Note:
- This is a follow up problem to Find Minimum in Rotated Sorted Array.
- Would allow duplicates affect the run-time complexity? How and why?
题意
将一递增数列的随机后半部分与前半部分换位,得到新数组,在新数组中查找最小值(数组中有重复的值)。
思路
与 0153. Find Minimum in Rotated Sorted Array 相比,允许数组中存在重复的值,这带来的问题是,很难根据一个元素与最左侧元素的大小关系来判断它是落在左区间还是右区间,如数组 [10, 10, 1, 10, 10, 10]。
因此在 0153. Find Minimum in Rotated Sorted Array 解法的基础上做出改动:只有当nums[mid]与nums[left]存在严格的大于小于关系时,才能确定mid是落在左区间还是右区间,而当nums[mid]等于nums[left]时,因为无法有效判断区间归属,只能令left右移(或者right左移)。在最坏情况下(全元素一样),时间复杂度退化至\(O(N)\)。
也可以用分治法实现。
代码实现
Java
二分法
class Solution {
public int findMin(int[] nums) {
int left = 0, right = nums.length - 1;
while (left < right) {
// 当前区间已经是有序区间,则最小值就是nums[left]
if (nums[left] < nums[right]) {
return nums[left];
}
int mid = left + (right - left) / 2;
if (nums[mid] < nums[right]) {
right = mid;
} else if (nums[mid] > nums[right]) {
left = mid + 1;
} else {
right--;
}
}
return nums[right];
}
}
分治法
class Solution {
public int findMin(int[] nums) {
return findMin(nums, 0, nums.length - 1);
}
private int findMin(int[] nums, int left, int right) {
if (left == right) {
return nums[left];
}
int mid = left + (right - left) / 2;
return Math.min(findMin(nums, left, mid), findMin(nums, mid + 1, right));
}
}
JavaScript
二分法
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function (nums) {
let left = 0, right = nums.length - 1
while (left < right) {
if (nums[left] < nums[right]) {
return nums[left]
}
let mid = Math.trunc((right - left) / 2) + left
if (nums[mid] < nums[left]) {
right = mid
} else if (nums[mid] > nums[left]) {
left = mid + 1
} else {
left++
}
}
return nums[left]
}
分治法
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function (nums) {
return dac(nums, 0, nums.length - 1)
}
let dac = function (nums, left, right) {
if (left === right) {
return nums[left]
}
let mid = Math.trunc((right - left) / 2) + left
return Math.min(dac(nums, left, mid), dac(nums, mid + 1, right))
}