剑指offer 面试题11 旋转数组中的最小数字

问题:把一个数组(给出的所有元素都大于0)最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
NOTE:若数组大小为0,请返回0。

输入:一个非递减排序的数组的一个旋转vector<int> array

输出:旋转数组的最小元素。

思路:如果顺序查找,时间复杂度为O(n),这里介绍一种时间复杂度为O(logn)的算法,基于二分查找,具体思路如下:

建立两个指针index1和index2,开始时分别指向数组头和尾。

a.因为是非递减排序的数组,当array[index1]<array[index2],表明未经过旋转,结果直接输出array[index1]即可。

b.当array[index1]>=array[index2]时,不能直接找出最小元素,取array[(index1+index2)/2]与头尾进行对比。

b.1.在缩小范围过程中,出现index2-index1==1时,则返回index2.再或者如果(array[index1]==array[index2])&&(array[index1]==array[(index1+index2)/2]),则无法使用二分法进行查找,只能转而使用顺序查找

b.2.如果array[index1]<=array[(index1+index2)/2],则最小的数在右半边,将index1赋为(index1+index2)/2

b.3.如果array[index2]>=array[(index1+index2)/2],则最小的数在左半边,将index2赋为(index1+index2)/2

代码:

class Solution {
public:
    int minNumberInRotateArray_SequenceFind(vector<int> array)
    {
        int result=array[0];
        int length=array.size();
        for(int i=1;i<length;i++)
        {
            if(array[i]<result)
                result=array[i];
        }
        return result;
    }
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.empty())
            return 0;
        int length=rotateArray.size();
        int index1=0;
        int index2=length-1;
        int midIndex=index1;
        while(rotateArray[index1]>=rotateArray[index2])
        {
            if((index2-index1)==1)
                return rotateArray[index2];
            midIndex=(index2+index1)/2;
            if((rotateArray[index1]==rotateArray[index2])&&(rotateArray[index1]==rotateArray[midIndex]))
                return minNumberInRotateArray_SequenceFind(rotateArray);
            if(rotateArray[index1]<=rotateArray[midIndex])
                index1 = midIndex;
            else if(rotateArray[index2]>=rotateArray[midIndex])
                index2 = midIndex;
            
        }
        return rotateArray[midIndex];
    }
};

复杂度分析:时间复杂度为O(n),空间复杂度为O(1)。

发布了56 篇原创文章 · 获赞 10 · 访问量 6798

猜你喜欢

转载自blog.csdn.net/qq_22148493/article/details/104425566
今日推荐