题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:旋转数列可以看做两个有序序列,前一个递增序列的最大值位置的下一位,几位整个数列的最小值的位置。可以采用二分查找的思路,从中间位置mid入手,array[head] < array[mid] 说明mid进入第一个递增序列,最小值在mid后面,更新head为mid。array[head] > array[mid] 说明mid处于第二个递增子序列中,最小值在mid前面,更新rear为mid。
最最最麻烦的是 :arrary[head] == array[mid] == array[rear],此时有三种情形。
- 1,1,1,1,1,0,1
- 1,0,1,1,1,1,1
- 1,1,1,1,1,1,1
这样的话,二分查找就失效了,此时只能采取顺序遍历的方式找最小值了。
算法中最重要的是: 要想到前一个递增序列的最大值位置的下一位,几位整个数列的最小值的位置,即
if (rear - head == 1) {
return array[rear];
}
这个是最后返回的判断条件。
参考代码如下:
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int[] array) {
if (array == null) {
return 0;
}
if (array.length <= 0) {
return 0;
}
return findMin(array, 0, array.length);
}
public int findMin(int[] array, int head, int rear) {
while (head < rear) {
if (rear - head == 1) {
return array[rear];
}
int mid = (head + rear) / 2;
if (array[mid] > array[head]) {
head = mid;
} else if (array[mid] < array[head]) {
rear = mid;
} else {
int min = array[head];
for (; head < rear; head++) {
if (min > array[head+1]) {
min = array[head];
}
}
return min;
}
}
return array[rear];
}
}