刷题:牛客JZ11 旋转数组的最小数字

153 阅读2分钟

网址: www.nowcoder.com/practice/9f…

描述

有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

数据范围:1 \le n \le 100001≤n≤10000,数组中任意元素的值: 0 \le val \le 100000≤val≤10000

要求:空间复杂度:O(1)O(1) ,时间复杂度:O(logn)O(logn)

public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int len=rotateArray.size();
        if(len==1)
        {
            return rotateArray[0];
        }
        int left=1;   //第零项不可能是数组的唯一的最小项,左界从第一项开始
        int right=len-1;
        int f=(left+right)/2;
        
        for(;right>=left;)
        {
            if(rotateArray[f-1]>rotateArray[f])   //只要满足这个判断,[f]项必定是最小项
            {
                return rotateArray[f];
            }
            else if(rotateArray[f]<rotateArray[0])
            {
                right=f-1;
                f=(left+right)/2;
            }
            else if(rotateArray[f]>rotateArray[0])
            {
                left=f+1;
                f=(left+right)/2;
            }
            //以下是[f]项与[0]项相等的情况
            else if(rotateArray[0]!=rotateArray[len-1])
            {
                left=f+1;
                f=(left+right)/2;
            }
            else{
                int i=f+1;
                for(;i<len;i++)   //不能判断处于左数列还是右数列,只能顺序判断
                {
                    if(rotateArray[i]!=rotateArray[0])
                    {
                        left=f+1;
                        f=(left+right)/2;
                        break;
                    }
                }
                if(i==len)
                {
                    right=f-1;
                    f=(left+right)/2;
                }
            }
        }
        return rotateArray[0];   //整个数组的值都相等的情况
    }
};

总结:

二分法的关键是找对左右界和比较值(target),此题中左右界很明显,从数组的左右界开始缩小就行。关键是找到比较值,这个值要能确定中间项(f)是处于左数列还是右数列。那这个target就是数组的左界或者右界,因为这两个数是整个数组旋转时的分界。

我选数组的左界[0]作为比较值target,如果中间项(f)大于[0],说明(f)处于左数列,将f+1作为新的左界进行缩小。(f)小于[0]则说明(f)处于右数列,将f-1作为新的右界进行缩小。

还有一种情况是中间项(f)==[0],这时(f)既有可能处于左数列的前面,也有可能处于右数列的后面。如果[0]不等于数组最后一项[len-1],说明(f)处于左数列。否则,只能顺序查找,来判断(f)在左数列还是右数列。

如果不要求用二分法解决,用sort函数排完序后直接输出数组[0]项。