题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
思路一:最直观一组数组中找一个最小值是遍历这组数据,时间复杂度O(n)
新思路:旋转数组的特性是一定程度上是有序的,而二分查找适用于排序数组。数组{3,4,5,1,2}可以拆分为2个排序数组,它满足:
1,前面子数组的元素都大于后面子数组的元素,{3,4,5} > {1,2}
2,最小的元素一定在子数组的分界线上。
解法:用两个指针分别指向数组的第一个和最后一个元素,
接着找到数组的中间元素,如果中间元素 大于 第一个头指针,表示最小的数一定在该中间元素所在子数组的后面,将头指针移动到中间元素后面,再次比较。反之亦然。
最终第一个指针一定会指向前面子序列的最后一个元素,后面的指针一定会指向后面子序列的第一个元素,当两个指针相邻时,循环结束。
列:arr={3,4,5,1,2} index1 = arr[0] =3; index2 = arr[4] = 2; mid = 5;
index1 = arr[2] = 5; index2 = arr[4] = 2; mid = 1;
index1 = arr[2] = 5; index2 = arr[3] = 1; 最小值为1
public class elevenXuanZhuan {
public static void main(String[] args) {
int [] arr={1,0,1,1,1};
int min = mid(arr, arr.length);
System.out.println(min);
}
public static int mid(int [] arr,int length) {
if(length<=0) return -1;
int index1 = 0;
int index2 = length-1;
int indexMid = index1; //初始化这个是当数组为 {1,2,3,4,5}时,第一个为最小值
while(arr[index1] >= arr[index2]) {
if(index2 - index1 == 1) {
indexMid = index2;
break;
}
indexMid = (index1 + index2) /2;
//考虑前中后都相等又不是最小值怎么办?
if(arr[index1] == arr[indexMid] && arr[indexMid] == arr[index2]) {
if(arr[index1+1] != arr[index2 -1]) {
indexMid = arr[index1+1] < arr[index2 -1] ?index1+1:index2-1;
}else {
index1++;
index2--;
}
}
if(arr[indexMid] >=arr[index1]) {
index1 = indexMid;
}else {
index2 = indexMid;
}
}
return arr[indexMid];
}
}
总结:排序,或者部分排序,抓住特性考虑二分查找的用法。