题目:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例子:
如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
链接:
剑指Offer(第2版):P82
LeetCode-153:Find Minimum in Rotated Sorted Array
思路标签:
算法:二分查找
解答:
1. C++
- 首先能想到的就是顺序遍历,数组中最小的元素即为整个旋转数组的最小元素,但算法时间复杂度为O(n);
- 由旋转数组的特性,因为经排序好的数组旋转得到的,所以由其特性可以知道,除了不旋转的情况(即原数组),旋转数组可以划分为两个排序的子数组,前面的子数组元素均大于后面的子数组元素,存在分界线,所以可以想到的就是利用二分查找法,实现时间复杂度为O(logn);
- 注意考虑以下几种情况的处理:
- 1)数组元素为空的情况,(判断,直接返回0);
- 2)数组元素只有一个的情况,(判断,直接返回该元素);
- 3)数组旋转0个元素,也就是没有旋转的情况,(最后返回mid对应的值,所以初始时令mid=low,遇到该情况while条件不成立,依然返回mid对应的值);
- 4)如,排序数组为{0,1,1,1,1},旋转数组为{1,0,1,1,1}或者{1,1,1,0,1},当为这两种情况时,mid=low=high,无法确定最小的元素在左还是在右,所以这个时候就需要采用顺序查找的方式。
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.size() == 0) return 0;
if(rotateArray.size() == 1) return rotateArray[0];
int low = 0;
int high = rotateArray.size()-1;
int mid = low;
while(rotateArray[low] >= rotateArray[high]){
// 结束条件
if(high - low == 1){
mid = high;
break;
}
mid = (low + high)/2;
//顺序查找
if(rotateArray[low] == rotateArray[high] && rotateArray[low] == rotateArray[mid])
return minInOrder(rotateArray, low, high);
if(rotateArray[mid] >= rotateArray[low])
low = mid;
else if(rotateArray[mid] <= rotateArray[high])
high = mid;
}
return rotateArray[mid];
}
int minInOrder(vector<int>& numbers, int low, int high){
int result = numbers[low];
for(int i = low+1; i<=high; ++i){
if(result > numbers[i])
result = numbers[i];
}
return result;
}
};
2. Java
- 考虑的情况较少。
http://blog.youkuaiyun.com/koala_tree/article/details/78477304