(剑指Offer)面试题8:旋转数组的最小数字

题目:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。

例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

思路:

1、遍历数组,找到数组的最小值,时间复杂度O(n);

2、二分查找,时间复杂度O(logn)

注意旋转数组的循环不变量,A[left]>=A[right](这道题的数组为非递减数组,并非严格的递增数组)

特例:无旋转情况以及{0,1,1,1,1,1}旋转数组

查找过程:

旋转数组可以看成两个递增(非减)数组,通过前后两个指针left,right分别指向数组的首尾,

当满足循环不变量时A[left]>=A[right],mid=(left+right)/2,

如果A[mid]>=A[left],说明最小值存在mid后面部分,left=mid;

如果A[mid]>=A[right],说明最小值存在mid前面部分,right=mid;

经过循环之后,最终left会指向第一个递增数组的最后一个数,right会指向第二个递增数组的第一个数,即最小值mid=right。

最终return A[mid];

解决特例问题:

  • 无旋转数组:数组就是递增的,返回第一个数,即A[left],因此mid=left即可;
  • {0,1,1,1,1,1}类似旋转数组:不满足上述查找过程,只能遍历数组。

代码:

#include <iostream>
#include <vector>

using namespace std;

int MinInOrder(int* arr,int left,int right){
    int result=arr[left];
    for(int i=left+1;i<=right;i++){
        if(result>arr[i])
            result=arr[i];
    }
    return result;
}

int Min(int* numbers,int length){
    if(numbers==NULL || length<=0)
        return -1;
    int left=0;
    int right=length-1;
    int mid=left;
    while(numbers[left]>=numbers[right]){
        if(right-left==1){
            mid=right;
            break;
        }
        mid=left+((right-left)>>1);
        if(numbers[left]==numbers[right] && numbers[left]==numbers[mid])
            return MinInOrder(numbers,left,right);
        if(numbers[mid]>=numbers[left])
            left=mid;
        else
            right=mid;
    }
    return numbers[mid];
}

int main()
{
    int A[]={1,0,1,1,1,1,1,1};
    int len=sizeof(A)/sizeof(A[0]);
    Solution s;
    vector<int> nums(A,A+len);
    cout<<s.minNumberInRotateArray(nums)<<endl;
    cout<<Min(A,len)<<endl;
    return 0;
}

在线测试OJ:

http://www.nowcoder.com/books/coding-interviews/9f3231a991af4f55b95579b44b7a01ba?rp=1

AC代码:

class Solution {
public:
	int minNumberInRotateArray(vector<int> rotateArray) {
		int len=rotateArray.size();
        if(len==0)
            return 0;
        int left=0;
        int right=len-1;
        int mid=left;
        //if(rotateArray[left]<rotateArray[right]);
        //	return rotateArray[left];
        while(rotateArray[left]>=rotateArray[right]){
            if(right-left==1){
                mid=right;
                break;
            }
            mid=left+((right-left)>>1);
            if(rotateArray[left]==rotateArray[right] && rotateArray[left]==rotateArray[mid])
                return MinInOrder(rotateArray,left,right);
            if(rotateArray[mid]>=rotateArray[left])
                left=mid;
            else
                right=mid;
        }
        return rotateArray[mid];
	}

	int MinInOrder(const vector<int> &arr,int left,int right){
        int result=arr[left];
        for(int i=left+1;i<=right;i++){
            if(result>arr[i])
                result=arr[i];
        }
        return result;
	}
};

  

你可能感兴趣的:(面试题)