问题:把一个数组(给出的所有元素都大于0)最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
NOTE:若数组大小为0,请返回0。
输入:一个非递减排序的数组的一个旋转vector<int> array
输出:旋转数组的最小元素。
思路:如果顺序查找,时间复杂度为O(n),这里介绍一种时间复杂度为O(logn)的算法,基于二分查找,具体思路如下:
建立两个指针index1和index2,开始时分别指向数组头和尾。
a.因为是非递减排序的数组,当array[index1]<array[index2],表明未经过旋转,结果直接输出array[index1]即可。
b.当array[index1]>=array[index2]时,不能直接找出最小元素,取array[(index1+index2)/2]与头尾进行对比。
b.1.在缩小范围过程中,出现index2-index1==1时,则返回index2.再或者如果(array[index1]==array[index2])&&(array[index1]==array[(index1+index2)/2]),则无法使用二分法进行查找,只能转而使用顺序查找
b.2.如果array[index1]<=array[(index1+index2)/2],则最小的数在右半边,将index1赋为(index1+index2)/2
b.3.如果array[index2]>=array[(index1+index2)/2],则最小的数在左半边,将index2赋为(index1+index2)/2
代码:
class Solution {
public:
int minNumberInRotateArray_SequenceFind(vector<int> array)
{
int result=array[0];
int length=array.size();
for(int i=1;i<length;i++)
{
if(array[i]<result)
result=array[i];
}
return result;
}
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.empty())
return 0;
int length=rotateArray.size();
int index1=0;
int index2=length-1;
int midIndex=index1;
while(rotateArray[index1]>=rotateArray[index2])
{
if((index2-index1)==1)
return rotateArray[index2];
midIndex=(index2+index1)/2;
if((rotateArray[index1]==rotateArray[index2])&&(rotateArray[index1]==rotateArray[midIndex]))
return minNumberInRotateArray_SequenceFind(rotateArray);
if(rotateArray[index1]<=rotateArray[midIndex])
index1 = midIndex;
else if(rotateArray[index2]>=rotateArray[midIndex])
index2 = midIndex;
}
return rotateArray[midIndex];
}
};
复杂度分析:时间复杂度为O(n),空间复杂度为O(1)。