题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
题目思考:
首先最直观的是遍历数组,当遇到第一组前面比其大,后面比其小的数时,即是答案。
这种算法的时间复杂度是O(n),但显然在这种排序数组的变式中,O(logn)的时间复杂度才是最优的,这就让我们想到使用二分法来解决。
实际上,遇到排序数组找数字题,最直观最有效的就是二分法。
具体的思路如下:
- 因为题目中并没有给我们一些范围,所以我们可以自己设置,可以每次以数组中间为间,分别判断左右两个区间。
- 如果左区间或者右区间是非递增的,那么就说明最小数在这个区间内,我们可以使用while循环迭代求解,也可以递归求解
- 最后需要注意的点是题目中的描述是非递减,所以就有可能遇到区间的两个端点相同的情况。在这种情况下,我们只需要移动端点的一端,再进行比较即可。
public int minNumberInRotateArray(int [] array) {
// 使用二分,判断条件是是否非递增
// 同时如果首尾相同,则收缩
if(array.length == 0){
return 0;
}
int low = 0;
int high = array.length - 1;
int mid = 0;
while(low < high){
// 子数组是非递减的数组,10111
if (array[low] < array[high])
return array[low];
mid = low + (high - low) / 2;
if(array[mid] > array[low])
low = mid + 1;
else if(array[mid] < array[high])
high = mid;
else low++;
}
return array[low];
}