剑指offer OJ,旋转数组的最小数字

时间限制:1秒空间限制:32768K
通过比例:15.05%
最佳记录:0 ms|8552K (来自 牛客841129号)
题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减序列的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

思想:采用二分法,定义low,mid,high下标。如果[mid]<[low]代表mid处于旋转过的部分中,反之处于主体部分中,特殊情况[mid]=[low]分情况考虑,这里注意[mid]>[low]有可能是旋转位数为0的情况,需要加判定。

我的代码:

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int low, high, mid;
        low = 0, high = rotateArray.size() - 1;
        //数组为空;
        if(high < 0) {
            return 0;
        }
        //数组不为空;
        //(1)数组只有一个或两个个元素;
        if(low >= high - 1) {
            if(rotateArray[low] < rotateArray[high]) {
                return rotateArray[low];
            }
            else {
                return rotateArray[high];
            }
        }
        //(2)数组有三个或更多元素;
        while(low < high - 1) {
            //mid选择算法;
            mid = (low + high)/2;
            if(rotateArray[mid] > rotateArray[low]) {
                //考虑旋转位数为0的情况;
                if(rotateArray[mid] < rotateArray[high]) {
                    return rotateArray[0];
                }
                else {
                    low = mid;
                }
            }
            else if(rotateArray[mid] < rotateArray[low]) {
                high = mid;
            }
            else if(rotateArray[mid] == rotateArray[low]) {
                if(rotateArray[mid] > rotateArray[high]) {
                    low = mid;
                }
                else if(rotateArray[mid] < rotateArray[high]) {
                    high = mid;
                }
                //特殊情况,不能判断mid归属;
                else {
                    int num = except(rotateArray);
                    return num;
                }
            }
        }
        return rotateArray[low] > rotateArray[high] ? rotateArray[high] : rotateArray[low];
    }
    //至少有一半元素相同所以只能顺序遍历;
private:
    int except(vector<int> rotateArray) {
        vector<int>::iterator it;
        int min;
        for(it = rotateArray.begin(); it != rotateArray.end(); it++) {
            if(it == rotateArray.begin()) {
                min = * it;
            }
            else {
                min = min <= *it ? min : *it;
            }
        }
        return min;
    }
};

如果数组较小直接遍历

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {

        if(rotateArray.size() == 0) {
            return 0;
        }
        else if(rotateArray.size() == 1) {
            return rotateArray[0];
        }
        return except(rotateArray);
};

在牛客网讨论区看到一个更简洁的代码,利用迭代器,省去了下标,看起来更加简洁,思想是当[mid]=[low]时将low自加一就行了,省去了繁琐的特殊情况考虑。

代码:

int minNumberInRotateArray(vector<int> rotateArray) { 
    size_t len = rotateArray.size();
    if(len == 0)
        return 0;
    if(len == 1)
        return rotateArray[0];
    vector<int>::iterator low = rotateArray.begin();
    vector<int>::iterator mid;
    vector<int>::iterator high = rotateArray.end();
    while(low <= high)
    {
        //防止迭代器失效
        mid = low + (high - low)/2;
        if(*mid >*high)
        {
            low = mid + 1;
        }
        else if(*mid < *high)
        {
            high = mid;
        }
        else
        {
            high = high-1;
        }
        if(low >= high)
        {
            break;
        }
    }
        return *low;
    }

 //防止迭代器失效这句我的理解是防止直接low + high造成地址空间溢出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值