今日份题目:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为 1。
注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。
示例1
输入:numbers = [3,4,5,1,2]
输出:1示例2
输入:numbers = [2,2,2,0,1]
输出:0提示
-  n == numbers.length
-  1 <= n <= 5000
-  -5000 <= numbers[i] <= 5000
-  numbers原来是一个升序排序的数组,并进行了1至n次旋转
题目思路
方法一:暴力搜索
从头到尾遍历数组,如果没有旋转的话应该从头到尾是递增数列,所以如果遇到某个数比前一个数小,那么这个数就是要找的最小的那个旋转的数,如果全程找不到那最小的那个旋转数就是第一个数。
代码
class Solution 
{
public:
    int minArray(vector<int>& numbers) 
    {
        int pre,cur;
        int n=numbers.size();
        if(n==1) return numbers[0];//注意先判断长度,如果只有一个元素,那么运行cur=numbers[1]会出错
        pre=numbers[0];
        cur=numbers[1];
        if(cur<pre) return cur;
        for(int i=2;i<n;i++)
        {
            pre=cur;
            cur=numbers[i];
            if(cur<pre) return cur;
        }
        return numbers[0];
    }
};提交结果

方法二:二分查找(官方给出)
numbers[mid]和numbers[r]之间会出现三种情况
第一种情况是 numbers[mid]<numbers[r]。如下图所示,这说明 numbers[mid]是最小值右侧的元素,因此我们可以忽略二分查找区间的右半部分。

第二种情况是 numbers[mid]>numbers[r]。如下图所示,这说明 numbers[mid]是最小值左侧的元素,因此我们可以忽略二分查找区间的左半部分。

第三种情况是 numbers[mid]==numbers[r]。如下图所示,由于重复元素的存在,我们并不能确定 numbers[mid]究竟在最小值的左侧还是右侧,因此我们不能莽撞地忽略某一部分的元素。我们唯一可以知道的是,由于它们的值相同,所以无论 numbers[r]是不是最小值,都有一个它的「替代品」numbers[mid],因此我们可以忽略二分查找区间的右端点。

(思路来源:作者:力扣官方题解 链接:力扣 来源:力扣(LeetCode))
代码
class Solution 
{
public:
    int minArray(vector<int>& numbers) 
    {
        int n=numbers.size()
        int l=0,r=n-1;
        while(l<=r) 
        {
            int mid=(l+r)/2;
            if(numbers[mid]<numbers[r]) r=mid;
            else if(numbers[mid]>numbers[r]) l=mid+1;
            else r--; 
        }
        return numbers[l];
    }
};提交结果

欢迎大家在评论区讨论,如有不懂的代码部分,欢迎在评论区留言!



![智慧工厂解决方案[60页PPT]](https://img-blog.csdnimg.cn/img_convert/4281e11a3403159fafa5f819ef57b567.jpeg)















