题目描述
旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
分析
顺序查找、二分查找
思路一:非递减数列的含义是对任意位置而已,a[k]<=a[k+1] (0<=k<n).那么对于旋转数组而言,若只要存在两个数时不等的,假设a[min]是最小值首次出现的位置,那么必然有a[min]<a[min-1],而对于其他全部位置有a[k]>=a[k-1].
若从左往右逐个查找,此方法的时间复杂度为O(n).
思路二:利用左右指针:
left指向数组左端,right指向数组右端,取mid = (left+right)/2;
比较a[mid] 与a[left] 的大小:此时有三种情况:
1.a[mid] == a[right] 。
此时并不好缩小数组,例如[1,1,0,1,1],可以将right左移一位,即
right -=1;
2.a[mid] > a[right]。
说明此时最小值在mid的左侧,故使left =mid,以缩小范围。
3.a[mid] < a[right]
说明此时最小值在left与mid之间,有可能就是mid,所以使right= mid 以缩小范围。
当left = right 时,跳出循环,此时两指针同时指向最小值。
思考时间复杂度,一般情况下,若数组中不含相同的数,那么复杂度在o(logN),若数组的元素完全相同,那么复杂度可能高达o(n)。具体用时要看数组中相同元素的个数了。
源码
顺序查找源码
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if (rotateArray.empty()) return 0;
else{
for(int ind =0;ind<rotateArray.size()-1;ind++){
if(rotateArray[ind]>rotateArray[ind+1])
return rotateArray[ind+1];
}
return rotateArray[0];
}
}
};
二分查找源码
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
vector<int> & a=rotateArray;
if(a.empty()) return 0;
int l=0;
int r=a.size()-1;
while(l<r)
{
int m = (l+r)/2;
if(a[m]<a[r]) r = m;
else if(a[m] ==a[r])
{
r--;
}
else
{
l = m+1;
}
}
return a[l];
}
};