题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
这里采用的方法是在讨论中学习到的方法,基于二分法的思想
用low和high指向两边,以及mid=low+(high-low)/2 指向中间
非减排序数组的旋转,表示,旋转了之后,原本大的数旋转到了数组的前面,也就是从中间有个分界,这个分界就是原来有序数组的最小值,为因此可以分为以下三种情况
1.如果位于mid的数大于high的数,则说明旋转后的数组,最小值在mid的右边且不包括mid(因为mid已经比high大了),因此要在[mid+1,high]这个区间开始进行下一步的查找
2.如果小于,则说明最小值在mid的左边且包括mid(因为mid可能就是这个最小值),因此high=mid
3.如果等于,则说明这是一个含有重复数字的数组,那么不能判断最小值位于mid的左边右边或者就是mid,就应该high-1继续进行遍历查找。
c++实现:
这个时间复杂度通常是O(logn),只有在数组为所有数字都重复的情况下为O(n)。
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if (rotateArray.size()==0)
return 0;
int low=0;
int high=rotateArray.size()-1;
while(low<high)
{
int mid=low+(high-low)/2;
//如果mid的数大于high的数,说明旋转后的最小数在mid的右边(不包括mid))
//因此下一步low从mid+1开始继续查找
if(rotateArray[mid]>rotateArray[high])
low=mid+1;
//如果小于,说明旋转后的最小数在mid的左边(包括mid)
//因此下一步要在mid的左边进行查找
else if (rotateArray[mid]<rotateArray[high])
high=mid;
//如果等于,这是一个含有重复数字的数组,只能一个个遍历查找
else
high=high-1;
}
return rotateArray[low];
}
};