一、题目
把一个数组最开始的若干个元素搬到数组的末尾, 我们称之数组的旋转。输入一个递增排序的数组的一个旋转, 输出旋转数组的最小元素。例如数组{3,4,5,1,2 }为{ 1,2,3,4,5}的一个旋转,该数组的最小值为1。
二、解题思路
Step1.和二分查找法一样,我们用两个指针分别指向数组的第一个元素和最后一个元素。
Step2.接着我们可以找到数组中间的元素:
如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最小的元素应该位于该中间元素的后面。我们可以把第一个指针指向该中间元素,这样可以缩小寻找的范围。如果中间元素位于后面的递增子数组,那么它应该小于或者等于第二个指针指向的元素。此时该数组中最小的元素应该位于该中间元素的前面。
Step3.接下来我们再用更新之后的两个指针,重复做新一轮的查找。
public static int getTheMin(int[] number) {
if (number == null || number.length <= 0) {
return -1;
}
if (number.length == 1) {
return number[0];
}
int low = 0;
int mid = low;
int high = number.length - 1;
while (number[low] >= number[high]) {
// 当处理范围只有两个数据时,返回后一个结果
// 因为numbers[low] >= numbers[high]总是成立,后一个结果对应的是最小的值
if (high - low == 1) {
return number[high];
}
mid = (low + high) / 2;
// 如果三个数都相等,则需要进行顺序处理,从头到尾找最小的值
if(number[mid]==number[low]&&number[mid]==number[high]) {
return minNumber(number,low,high);
}
// 如果中间位置对应的值在前一个排好序的部分,将low设置为新的处理位置
if(number[mid] >=number[low]) {
//代表中间元素在左边递增子数组 ,因为后边的元素都是小于mid的元素
low=mid;
}else {
// 如果中间位置对应的值在后一个排好序的部分,将high设置为新的处理位置
high=mid;
}
}
return number[mid];
}
public static int minNumber(int[] number, int low, int high) {
int result = number[low];
for (int i = low + 1; i <= high; i++) {
if (result > number[i]) {
result = number[i];
}
}
return result;
}
=========================================
优化
public static int getTheMin1(int[] array) {
int low = 0;
int high = array.length - 1;
while (low < high) {
int mid = low + (high - low) / 2;// mid=(high+low)/2;
if (array[mid] > array[high]) {
low = mid + 1;
} else if (array[mid] == array[high]) {
high = high - 1;
} else {
high = mid;
}
}
return array[low];
}
//不同情况的事例
public static void increaseRotate() {
// 典型输入,单调升序的数组的一个旋转
int[] array1 = {3, 4, 5, 1, 2};
printNumber("array1", getTheMin(array1));
// 有重复数字,并且重复的数字刚好的最小的数字
int[] array2 = {3, 4, 5, 1, 1, 2};
printNumber("array2", getTheMin(array2));
// 有重复数字,但重复的数字不是第一个数字和最后一个数字
int[] array3 = {3, 4, 5, 1, 2, 2};
printNumber("array3", getTheMin(array3));
// 有重复的数字,并且重复的数字刚好是第一个数字和最后一个数字
int[] array4 = {1, 0, 1, 1, 1};
printNumber("array4", getTheMin(array4));
// 单调升序数组,旋转0个元素,也就是单调升序数组本身
int[] array5 = {1, 2, 3, 4, 5};
printNumber("array5", getTheMin(array5));
// 数组中只有一个数字
int[] array6 = {2};
printNumber("array6", getTheMin(array6));
// 数组中数字都相同
int[] array7 = {1, 1, 1, 1, 1, 1, 1};
printNumber("array7", getTheMin(array7));
// 特殊的不知道如何移动
int[] array8 = {1, 0, 1, 1, 1};
printNumber("array8", getTheMin(array8));
int[] array9 = {6, 6, 8, 9, 10, 1, 2, 2, 3, 3, 4, 5, 6};
printNumber("array9", getTheMin(array9));
}