旋转数组的最小数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
分析:原始数组为一个非递减排序,因此,我们旋转后,可知该数组应当是两个非递减序列组成,并且右侧序列的最右端(即最大值)一定不大于左侧序列的最左端(即最小值)
可以举一个具体例子来分析
给定数组 1,2,3,4,5
旋转后可以为 3,4,5,1,2
因此可以看出 3,4,5 1,2 分别是非递减序列
因此根据该性质,易知可用二分查找
- 找到区域边界两个位置 i i i, j j j
- 如果 左<右 ,很显然数组没有发生旋转,否则一定是左<=右
- 找到中间位置
m
i
d
mid
mid
- 如果中间位置的值小于右侧,说明最小值在右侧,令 i = m i d + 1 i=mid+1 i=mid+1 ,返回最初循环
- 如果中间位置的值大于右侧,说明最小值在左侧,令 j = m i d − 1 j=mid-1 j=mid−1 ,返回最初循环
- 如果中间位置的值等于右侧,则没办法确定最小值的位置,此时令 i i i++ 继续推进循环即可
- 直至i=j,即找到最小值
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray)
{
int size=rotateArray.size();
int i=0,j=size-1;
while(i<j)
{
if(rotateArray[i]<rotateArray[j]) //说明数组没有旋转
return rotateArray[i];
int mid=(i+j)>>1;
if(rotateArray[mid]>rotateArray[j])
{
i=mid+1;continue; //注意这里i=mid+1
}
if(rotateArray[mid]<rotateArray[j])
{
j=mid; //j=mid 主要是让i和j必须保持相近,避免二者相邻时出现死循环
continue;
}
if(rotateArray[mid]==rotateArray[j])
{
i++;
}
}
return rotateArray[i];
}
};