一、题目描述

JZ6旋转数组的最小数字
题目大意:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
注意审题:给出的所有元素都大于0,若数组大小为0,请返回0

二、算法1(暴力遍历)

算法思路

总体思想:遍历一遍数组并不断更新最小值即可,可以拿第一个元素作为初始的最小值

代码实现(C++11)

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.empty()) return 0;
        int ans = rotateArray[0];
        for(int& x : rotateArray){
            ans = min(ans, x);
            }
        return ans;
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

三、算法2(二分法)

算法思路

1.总体思路:由于原数组是非递减的,因此我们联想到是否可以用二分法解决,由于旋转后最多有两段非递减的序列,因此我们可以使用二分法来寻找最小值
2.根据二分法的步骤,我们可以根据中间值的大小来确定区间的缩小,就本题来说,我们可以通过与右指针所指的值相比来作为划分的依据,由于可能存在重复的值,因此可能出现mid所指的值与右指针所指的值相同的情况,此时我们只能将右指针向右移动;当mid所指的值小于右指针r所指的值时,就将右指针移动至mid处,区间缩短为[l,mid];当mid所指的值大于右指针r所指的值时,将左指针移动至mid + 1处即可,此算法的平均时间复杂度是O(logn)
3.由于可能存在重复的值,因此最坏的情况下整个数组的值都相同,此时要不断的移动右指针,时间复杂度退化至O(n)

代码实现 (C++11)

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.empty()) return 0;
        int l = 0, r = rotateArray.size() - 1;
        while(l < r){
            int mid = l + r >> 1;
            if(rotateArray[mid] < rotateArray[r]) r = mid;
            else if(rotateArray[mid] > rotateArray[r]) l = mid + 1;
            else --r;
            }
        return rotateArray[l];
    }
};

时间复杂度:平均时间复杂度O(logn), 最坏时间复杂度O(n)
空间复杂度:O(1)