旋转数组的最小数字

来源:互联网 发布:sql语句 修改 编辑:程序博客网 时间:2024/06/17 17:08

题目

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

思路

由题意可知,整个数组可以看成两块连续非递减的区域,并且后一个区域的最大值不会大于前一个区域的最小值,并且最小值为后一个区域的第一个值。使用二分法进行查找,假设mid为二分得到的中间元素,left和right为查找区域的左端和右端,那么有三种情况:
1. mid 大于区间最右边的值,类似于[3, 4, 5, 6, 7, 1, 2]这种,mid为6,说明最小值只可能在mid右边的区域,所以left = mid下标+1
2. mid 小于区间最右边的值,类似于[5, 6, 1, 2, 3, 4]这种,mid为1,说明最小值只可能出现在mid左边的区域或者就是mid,所以right = mid下标
3. mid 等于区间最右边的值,这种情况无法判断,比如[1, 1, 1, 1, 0, 1]和[1, 1, 0, 1, 1, 1, 1, 1]这两种,mid为1,但是最小值可能在mid的左边区域,也可能在mid的右边区域,只能从left到right的区间内部都扫描一遍得到最小值。

参考代码

class Solution {public:    int minNumberInRotateArray(vector<int> rotateArray) {        if(rotateArray.size() == 0) return 0;        int len = rotateArray.size() - 1;        if(rotateArray[0] < rotateArray[len]) return rotateArray[0];        int i = 0, j = len, middle;        while(i < j){            middle = i + (j - i) / 2;            if(rotateArray[middle] < rotateArray[j]) {                j = middle;            }else if(rotateArray[middle] > rotateArray[j]) {                i = middle + 1;            }else{                return SearchForMin(rotateArray, i, j);            }        }        return rotateArray[i];    } private:    int SearchForMin(vector<int>& nums, int left, int right){        int minNum = nums[left];        for(int i = left + 1; i <= right; ++i) {            if(nums[i] < minNum) minNum = nums[i];        }        return  minNum;    }};
原创粉丝点击