Find Minimum in Rotated Sorted Array I
Suppose a sorted array 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.
You may assume no duplicate exists in the array.
二分迭代法
复杂度
时间 O(N) 空间 O(N) 递归栈空间
思路
4 5 6 7 0 1 2
|
| |
| | |
| | | |
| | | |
| | | | |
| | | | | |
找旋转数组的起点,实际上类似找一个山谷,只要两边都比中间高就对了,这和Find Peak Element这题很像。我们不断地取中点,找左右两侧较小的那一侧,直到找到一个点比左右两边都低。
注意
在二分到两头的时候要特殊处理一下,返回两头和两头第二个中最小的。
代码
public class Solution {
public int findMin(int[] nums) {
for(int min = 0, max = nums.length - 1, mid = max / 2; min <= max; mid = (min + max)/2){
// 如果找到最左边,返回较小的那个
if(mid == 0) return Math.min(nums[mid],nums[max]);
// 如果找到最右边,返回较小的那个
if(mid == nums.length - 1) return Math.min(nums[mid],nums[min]);
// 如果两边都比中间高,返回中间那个
if(nums[mid] < nums[mid-1] && nums[mid] < nums[mid+1]) return nums[mid];
// 否则,继续搜索较小的那一半,找到低谷
if(nums[mid] > nums[max]){
min = mid + 1;
} else {
max = mid - 1;
}
}
return nums[0];
}
}
二分模板
public class Solution {
public int findMin(int[] nums) {
int min = 0, max = nums.length - 1;
while(min <= max){
int mid = min + (max - min) / 2;
if(mid == 0) return Math.min(nums[mid], nums[max]);
if(mid == nums.length - 1) return Math.min(nums[mid], nums[min]);
if(nums[mid + 1] >= nums[mid] && nums[mid - 1] >= nums[mid]){
return nums[mid];
} else if(nums[mid] > nums[max]){
min = mid + 1;
} else {
max = mid - 1;
}
}
return nums[0];
}
}
二分递归法
复杂度
时间 O(N) 空间 O(N) 递归栈空间
思路
递归法实现起来更加简洁清晰。当min
等于max
时,我们锁定了那个最小值。那如何判断在哪一半呢,如果num[max] > num[mid]
,说明右边都是有序的,所以那个旋转点必在左半边,也就是min
到mid
之间,如果num[max] < num[mid]
,说明右边有问题,不过mid
点本身肯定不是最小值,他已经大于num[max]
了,所以在mid+1
和max
之间
注意
min == max
时随便返回一个
代码
public class Solution {
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
private int findMin(int[] num, int min, int max){
if(min == max){
return num[min];
}
int mid = (min+max)/2;
if(num[max] > num[mid]){
return findMin(num, min, mid);
} else {
return findMin(num, mid+1, max);
}
}
}
Find Minimum in Rotated Sorted Array II
Follow up for "Find Minimum in Rotated Sorted Array": What if duplicates are allowed?
Would this affect the run-time complexity? How and why? Suppose a sorted array 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.
二分递归法
复杂度
时间 O(N) 空间 O(N) 递归栈空间
思路
如果有重复的话,一旦中间和右边是相等的,就无法确定是否在左半边还是右半边,这时候我们必须对两边都递归求解。如果nums[max]
大于等于nums[mid]
,则右边有可能有,如果nums[max]
小于等于nums[mid]
,则左边有可能有。
注意
要先将左和右的最小值初始化最大整数,然后求解后,最后返回其中较小的那个
代码
public class Solution {
public int findMin(int[] nums) {
return findMin(nums, 0, nums.length - 1);
}
public int findMin(int[] nums, int min , int max){
if(min == max){
return nums[min];
}
int mid = (min + max) / 2;
// 先将右边和左边可能找到的值都初始化为最大
int right = Integer.MAX_VALUE, left = Integer.MAX_VALUE;
// 找出右边可能的旋转点
if(nums[mid] >= nums[max]){
right = findMin(nums, mid + 1, max);
}
// 找出左边可能的旋转点
if (nums[mid] <= nums[max]) {
left = findMin(nums,min, mid);
}
// 返回两个中更小的
return Math.min(right,left);
}
}