牛客网剑指Offer系列——旋转数组的最小数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
题目解析
非递减排序的数组进行旋转之后,会变成两个非递减数组的组合,例如1 2 2 3 4 5,旋转变成了2 3 4 5 1 2,第一种解法就是遍历数组直到发现数组中的元素小于前一个元素,该元素就是最小元素,时间复杂度为O(n)。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int size = rotateArray.size();
//数组长度为0
if(!size) return 0;
//数组部分旋转
for(int i=0;i<size-1;i++){
if(rotateArray[i]>rotateArray[i+1]){
return rotateArray[i+1];
}
}
//数组完全旋转
return rotateArray[0];
}
};
第二种解法就是简单的二分查找的变形,旋转数组具有一定程度的顺序,最小元素是两个非递减数组的边界元素,且第一个非递减数组的大小不小于第二个非递减数组。如1 2 2 3 4 5,旋转为2 3 4 5 1 2,第一个非递减数组为2 3 4 5,第二个非递减数组为1 2,最小元素即使第二个递减数组的第一个元素1。
若以mid为下标的元素的前一个元素大于它,则最小元素就是它;或者它的后一个元素小于它,则最小元素就是后一个元素。否则进行二分查找,以mid为下标的元素大于以low为下标的元素,说明最小元素在后半部分,令low=mid+1。反之,若mid下标的元素小于以low为下标的元素,说明最小元素在前半部分,令high=mid-1。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int size = rotateArray.size();
//数组长度为0
if(!size) return 0;
//数组完全旋转
if(rotateArray[0]<rotateArray[size-1])
return rotateArray[0];
//数组部分旋转
int low=0,high=size-1,mid=0;
while(low<=high){
mid=(low+high)/2;
if(rotateArray[mid]<rotateArray[mid-1])
return rotateArray[mid];
if(rotateArray[mid]>rotateArray[mid+1])
return rotateArray[mid+1];
if(rotateArray[mid]>rotateArray[low])
low=mid+1;
else if(rotateArray[mid]<=rotateArray[low])
high=mid-1;
}
return 0;
}
};