题目
题目链接
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [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
解题思路1
排序取最小元素 调用api 不推荐
代码
class Solution {
public int minArray(int[] numbers) {
Arrays.sort(numbers);
return numbers[0];
}
}
解题思路2
二分查找,不断缩减区间。分治思想。
题目要求旋转数组,其实有可能是2个递增区间
情况1:
例如【3,4,5,1,2】 的【3,4,5】和【1,2】
l指向3 r指向2,取中间索引指向5
我们以中间索引指向的值和r指向的值进行比较:5>2,于是我们一定能确定最小值一定不在【3,4,5】这个区间中,缩减区间只留下【1,2】
在此判断1<2 在此缩短区间留下1为最小值。
情况2:
例如【1,1,1,2,2,2】
l指向最左边的1 r指向最右边的2 取中间索引指向1
我们以中间索引指向的值和r指向的值进行比较:1<2 于是我们一定能确定最小值不在【2,2,2】区间中,缩减区间留下【1,1,1】
在这个区间中 1=1 所以我们在此缩短区间将最右边的1抛出也是不影响结果的 留下区间【1,1】同理1=1 留下区间【1】
找到最小值
代码
class Solution {
public int minArray(int[] numbers) {
//判空操作
if(numbers.length==0){
return 0;
}
//left指针指向数组第一个元素
int l = 0;
//right指针指向数组最后一个元素
int r = numbers.length - 1;
//退出条件,左右指针重合
while (l < r) {
int mid = l+((r-l)>>1);
//上述例子情况2
//下一轮搜索区间[l,mid]
if (numbers[mid] < numbers[r]) {
r = mid;
}
//上述例子情况1
//下一轮搜索区间是 [mid+ 1, r]
else if (numbers[mid] > numbers[r]) {
l = mid + 1;
}
//上述例子情况2
//下一轮搜索区间是 [l, r- 1]
else if (numbers[mid] == numbers[r]) {
r = r - 1;
}
}
return numbers[l];
}
}