题目分析

给定数组为一个升序数组的旋转形式,即将小于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];
        
    }
};