解题思路
二分查找变形+递归,是第153题的延伸题目(允许数组有重复元素)
由题意得,nums数组共有两种情况:
- 分为左右两段非降序数组,且左整体上大于右;
- 一整个非降序数组;
循环体中以中间值与两端点值比较作判断,分五种情况:
- 中间值小于左端时,表明nums数组处于第一种情况,且中间值位于第二段数组,最小元素必在左半边(包括中间值),如:[1,2,0,1,1],[2,0,1,1,1];
- 中间值大于右端时,表明nums数组处于第一种情况,且中间值位于第一段数组,最小元素必在右半边(不包括中间值),如:[1,1,1,0,0],[1,2,3,4,0];
- 中间值等于左端且小于右端时,表明nums数组处于第二种情况,最小元素即左端点,如:[0,0,0,1,2];
- 中间值等于右端且大于左端时,表明nums数组处于第二种情况,最小元素即左端点,如:[0,1,2,2,2];
- 中间值与两端均相等时,无法判断nums处于哪种情况,需要递归对两边分别二分查找,如:[1,1,1,0,1],[1,0,1,1,1],[1,1,1,1,1]。
class Solution {
public:
int Min_l_r(vector<int>& nums,int l,int r) {
if(l == r) return nums[l];
while(r - l > 1) {
int mid = (l+r)/2;
if(nums[mid] < nums[l]) r = mid;
else if(nums[mid] > nums[r]) l = mid+1;
else if(nums[mid] == nums[l] && nums[mid] < nums[r]) return nums[l];
else if(nums[mid] == nums[r] && nums[mid] > nums[l]) return nums[l];
else return min(Min_l_r(nums,l,mid-1),Min_l_r(nums,mid+1,r)); //if(nums[mid] == nums[l] && nums[mid] == nums[r])
}
return min(nums[l],nums[r]);
}
int findMin(vector<int>& nums) {
return Min_l_r(nums,0,nums.size()-1);
}
};
平均时间复杂度O(logN),最坏时间复杂度O(N)(数组内全为同一元素时)。
空间复杂度O(1)。