题目分析
给定数组为一个升序数组的旋转形式,即将小于nums.size()个头部data,不变换先后顺序的前提下放入尾部,形成一个新数组,数组装在一个vector容器中,寻找其中最小值。
思路分析
思路一:通过algorithm库中的sort函数,将[v.begin(),v.end())前闭后开区间的data进行升序排序,然后返回nums[0]的值即为题解。这是本题最简单,也是最好想到的思路。但是这样的思路显然不是此题所表达的思路,而且在传入引用的前提下,这样的做***影响容器中数据的排序。因此不可取。
思路二:通过二分查找。思路如下(图源:负雪明烛,LeetCode)。
在题目分析中我们可以知道,在“数组旋转”的过程中,无论是移到尾部的那些数据,还是变到头部的那些数据,都没有改变其升序的排列顺序。因此我们可以选择nums中间位置的元素,将其与nums最后一个元素作比较。
若nums[mid]>nums[right],则说明nums[mid]位于前一个升序序列,此时最小值应当位于mid的右侧,改变left的值;
若nums[mid]<nums[right],则说明nums[mid]位于后一个升序序列,此时最小值应当位于mid的左侧或就是mid位置的nums值,改变right的值;
还有一种特殊情况,即原升序序列中有重复元素,会导致nums[mid]=nums[right]的情况出现,此时无法判断mid位于哪个序列中,此时可以将left++来缩小范围。
代码如下:
class Solution {
public:
int findMin(vector<int>& nums) {
int left=0;
int right=nums.size()-1;
int mid;
while(left<right){
//left<right时循环,left=right时退出循环
if(nums[left]<nums[right]){
return nums[left];
}
mid=(left+right)/2;
if(nums[mid]<nums[right]){
right=mid;
}
if(nums[mid]>nums[right]){
left=mid+1;
}
else{
left++;
}
}
return nums[left];
}
};