把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
public static int min(int a[]){
if(a.length==1){//如果数组中只有一个元素则返回自己
return a[0];
}
int left = 0;
int right = a.length-1;
if (a[left] < a[right]){//如果最左大于最右代表按顺序排列好的,只需返回最左端的最小值
return a[0];
}
if(a[left]==a[right]){//如果最左等于最右,代表输入的数据有重复且没有规律,就按普通方法找最小值
int min = a[0];
for(int i =0;i<=a.length-1;i++){
if(a[i]<min){
int temp = a[i];
a[i] = min;
min = temp;
}
}
return min;
}
while(left<right){
int mid = (left+right)/2;
if(mid>left){
left=mid+1;
}
else if(mid<right){
right=mid;
}else{
right--;
}
return a[left];
}
return -1;
}
如果用二分查找的话,当中间的值大于最右边的值的时候,那么最小值一定在mid和right中间,当中间值小于最左边值的时候,最小值一定在left和mid中间,只有当right mid 和 left的值相同的时候才无法确定 最小值在哪个区间,无法确定的时候让right的值 自减就好,因为right的一定是大于等于最小值的
测试用例:
public static void main(String[] args) {
int[] array1 = {3, 4, 5, 1, 2};
System.out.println("array1:"+min(array1));
// 有重复数字,并且重复的数字刚好的最小的数字
int[] array2 = {3, 4, 5, 1, 1, 2};
System.out.println("array2:"+min(array2));
// 有重复数字,但重复的数字不是第一个数字和最后一个数字
int[] array3 = {3, 4, 5, 1, 2, 2};
System.out.println("array3:"+min(array3));
// 有重复的数字,并且重复的数字刚好是第一个数字和最后一个数字
int[] array4 = {1, 0, 1, 1, 1};
System.out.println("array4:"+min(array4));
int[] array41 = {1, 1, 1, 0, 1};
System.out.println("array41:"+min(array41));
// 单调升序数组,旋转0个元素,也就是单调升序数组本身
int[] array5 = {1, 2, 3, 4, 5};
System.out.println("array5:"+min(array5));
// 数组中只有一个数字
int[] array6 = {2};
System.out.println("array6:"+min(array6));
// 数组中数字都相同
int[] array7 = {1, 1, 1, 1, 1, 1, 1};
System.out.println("array7:"+min(array7));
}
array1:1
array2:1
array3:1
array4:0
array41:0
array5:1
array6:2
array7:1