Suppose an array of length n
sorted in ascending order is rotated between 1
and n
times. For example, the array nums = [0,1,4,4,5,6,7]
might become:
[4,5,6,7,0,1,4]
if it was rotated4
times.[0,1,4,4,5,6,7]
if it was rotated7
times.
Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]]
1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
.
Given the sorted rotated array nums
that may contain duplicates, return the minimum element of this array.
Example 1:
Input: nums = [1,3,5] Output: 1
Example 2:
Input: nums = [2,2,2,0,1] Output: 0
Constraints:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums
is sorted and rotated between1
andn
times.
Follow up: This is the same as Find Minimum in Rotated Sorted Array but with duplicates. Would allow duplicates affect the run-time complexity? How and why?
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?
寻找旋转有序数组的最小值之二。
思路跟版本一很接近,唯一多的一个条件是如果input里面有重复数字怎么办。这里需要多一个判断条件,如果判断不出来mid和end之间的大小关系,只能尝试end--,因为说明end和mid的值是一样的。所以这题worst case的时间会到O(n)。这道题跟153题一样,我还是选择使用 while (start + 1 < end) 这个模板,这样我最后需要额外判断 nums[start] 和nums[end],但是因为是找最小值而不是找目标值所以这个模板我个人觉得做起来比较方便。
时间O(logn), worst case O(n)
空间O(1)
JavaScript实现
1 /** 2 * @param {number[]} nums 3 * @return {number} 4 */ 5 var findMin = function(nums) { 6 // corner case 7 if (nums === null || nums.length === 0) return -1; 8 9 // normal case 10 let start = 0; 11 let end = nums.length - 1; 12 while (start + 1 < end) { 13 let mid = Math.floor(start + (end - start) / 2); 14 if (nums[mid] < nums[end]) { 15 end = mid; 16 } else if (nums[mid] > nums[end]) { 17 start = mid + 1; 18 } else { 19 end--; 20 } 21 } 22 if (nums[start] < nums[end]) return nums[start]; 23 else return nums[end]; 24 };
Java实现
1 class Solution { 2 public int findMin(int[] nums) { 3 int start = 0; 4 int end = nums.length - 1; 5 // start + 1 < end 6 // 举例,start - 0, end = 3 7 // 中间隔了起码有start + 1和start + 2两个下标 8 // 这样跳出while循环的时候,end < start 9 // 才有了最后的两个特判 10 while (start + 1 < end) { 11 int mid = start + (end - start) / 2; 12 if (nums[mid] < nums[end]) { 13 end = mid; 14 } else if (nums[mid] > nums[end]) { 15 start = mid; 16 } else { 17 end--; 18 } 19 } 20 if (nums[start] < nums[end]) { 21 return nums[start]; 22 } else { 23 return nums[end]; 24 } 25 } 26 }