剑指offer的一道经典题目。
描述
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围:1≤n≤10000,数组中任意元素的值: 0≤val≤10000
要求:空间复杂度:O(1) ,时间复杂度:O(logn)
解答:对于旋转数组,我们可以将它看作两个有序的数组。我们可以借助二分法来解决这个问题。根据区间中点值和区间最右边的值的关系来判断最小值在左半区间还是在右半区间。
第一步:取得区间左右指针,求出中点指针 第二步:若是区间中点值大于区间右界值,则最小的数字一定在中点右边;若是区间中点值等于区间右界值,则是不容易分辨最小数字在哪半个区间,比如[1,1,1,0,1],应该逐个缩减右界;若是区间中点值小于区间右界值,则最小的数字一定在中点左边。 第三步:通过调整区间最后即可锁定最小值所在。
代码:
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
int left = 0;
int right = array.length - 1;
while(left < right){
int mid = (left + right) / 2;
//最小的数字在mid右边
if(array[mid] > array[right])
left = mid + 1;
//无法判断,一个一个试
else if(array[mid] == array[right])
right--;
//最小数字要么是mid要么在mid左边
else
right = mid;
}
return array[left];
}
}