这个问题投机的做法就是将数组排序然后输出最小元素。但这种做法并不推荐,原因就不解释了。
这道题最好的做法是使用二分法。在解决这个问题前,先假设数组是一个元素互异且递增的数组。那么其中一定满足nums[n]>nums[0]。当此数组发生了旋转后,则必有nums[n]<nums[0]。此时,我们可以利用这一条件结合二分法来查找最小元素。如果nums[mid]<nums[0],则说明最小元素在mid左侧,否则说明在右侧。以此就可以逐步缩小区间直至找到最小元素。
不过,题目说明了数字中可能存在重复元素。那么有没有必要对所有的元素进行去重操作呢?答案是:如果nums[0]==nums[n]则需要对数组尾端等于nums[0]的元素进行去重操作,否则的话不需要。也就是说只要保证nums[n]<nums[0]就可以了。具体的实例可以参考题解。
具体代码如下:
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.empty()) return -1;
int n = nums.size() - 1;
while(n > 0 && nums[n] == nums[0]) n--; //数组尾部去重
if(nums[n] >= nums[0]) return nums[0]; //数组是单调的,没有发生旋转
int lo = 0, hi = n;
while(lo < hi){
int mid = (lo + hi) >> 1;
if(nums[mid] < nums[0]) hi = mid;
else lo = mid + 1;
}
return nums[hi];
}
};