题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组 { 3, 4, 5, 1, 2 } 为 { 1, 2, 3, 4, 5 } 的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
package test.test;
/**
* 递增数组的旋转数组 如:{1, 2, 3, 4, 5}的旋转数组之一是{3, 4, 5, 1, 2}
* 即:将 123 三个数旋转到末尾,此时数组是两个递增数组 345 和 12 ,前面数组的值都会大于后面数组的值。
* 最小值就是两个数组的分界值,也是后面较小数组的第一个值。此时可以利用类似二分法来查找
* min是首位,max是末位,mid = (min + max) / 2
* 若 array[mid] > array[min] 则说明 mid 位处于前半组较大的数组内,分界值在mid位后,所以令min = mid;
* 若 array[mid] < array[min] 则说明 mid 位处于后半组较小的数组内,分界值在mid位前,所以令max = mid;
* 按此赋值,min 始终位于前面较大数组内,max 始终位于后面较小数组内
* 直到min是较大数组的最后一位,同时max为较小数组第一位,此时他们相差1, 最小值就是max位所在值。
*
* 当 min mid max 三个位置的值都相等时, 比如:{1,0,1,1,1} 和 {1,1, 1,0,1}
* 此时无法判断分界值0到底处于前半段还是后半段,因此此时只能暴力查找了。
*
*/
public class TestMinNumberInRotateArray {
// array为一递增数组的旋转数组 如:{3,4,5,1,2}
public int minNumberInRotateArray(int[] array) {
int min = 0;
int max = array.length - 1;
int mid = min;
while (array[min] >= array[max]) {
if (max - min == 1) {
mid = max;
break;
}
mid = (min + max) / 2;
// 若前中后三个位置的大小一致,则无法判断分界值在前半段还是后半段,只能暴力搜索了。
if (array[min] == array[mid] && array[max] == array[mid]) {
for (int i = min; i < max; i++) {
if (array[i] > array[i+1]) {
return array[i+1];
}
}
}
if (array[mid] >= array[max]) {
min = mid;
} else if (array[mid] < array[max]) {
max = mid;
}
}
return array[max];
}
public static void main(String[] args) {
System.out.println(new TestMinNumberInRotateArray().minNumberInRotateArray(new int[] { 1, 1, 1, 1, 0 }));
}
}