把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
示例 2:
输入:[2,2,2,0,1]
输出:0
class Solution {
//临界点的题 二分
public int minArray(int[] numbers) {
//3 4 5 1 2 3 3 3
//3 4 5 1 2
int n = numbers.length-1;
if(n<0) return -1;
while(n>0 && numbers[n] == numbers[0]) n--;
if(numbers[0]<=numbers[n]) return numbers[0];
//二分
int l = 0,r= n;
while(l<r){
int mid = (l+r)/2;
if(numbers[mid]<numbers[0]) r= mid;
else l =mid+1;
}
return numbers[l];
}
}
思路:
1旋转数组的题其实可以看做是带临界点的题,这个临界点也就是数组的第一个值
2首先我们要判断数组是否为空,为空就返回-1
3像代码中的给出的样例3 4 5 1 2 3 3 3 3是比较特殊的样例,这种解法必须保证数组末尾的数字不能跟数组第一个数组相等,所以采用while(n>0 && numbers[n] == numbers[0]) n--;代码来解决这个问题
4接下就可以判断数组是否已经是一个排好序的数组了,如果是就直接输出数组中的第一个数。这个判断不能拿到第三步之前,如果拿到前面第三步中给出的样例3 4 5 1 2 3 3 3 3最终输出结果为3,错误!!!
5接下来采用二分法来做即可
首先将数组分成了[0,mid] 和[mid,n]这两个区间 那么中间的数比第一个数要小的话,那就得向左缩小位置,即r=mid
举个例子 6 7 1 2 3 4 5 中间的数为2 比7小 根据最小值1可以看到 向左边缩小位置
中间的数比第一个数组还要大的话,那就向右缩小位置 l =mid+1
举个例子 3 4 5 1 2 中间的数为5 比3大 根据最小值1可以看到 向右边缩小位置