/**
* 剑指offer面试题8:旋转数组的最小数字
*
* 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,
* 输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.
*
* 考查:二分查找的理解
*
* 思路: 在排序数组中,可以使用二分查找法进行查找
* 旋转之后的数组实际上可以划分2个有序的数组,前面的数组元素始终大于等于后一个数组元素,即可以得到最小的元素刚好
* 是这两个子数组的分界线。那么利用左右两个指针和中间指针元素大小关系判断中间元素是位于前面的子数组还是后面的子数组,缩小查找范围。
*
* 特殊情况:
* 1,排序数组本身仍是该数组的一个旋转,直接返回第一个元素
* 比如{1,2,3,4,5}
* 2,如果数组内有重复元素,那么有可能出现左右两指针元素与中间元素相同,无法判断中间元素属于前面子数组还是后面子数组,此时用顺序查找
* 比如{1,0,1,1,1}和{1,1,1,0,1}
*/
public class MinDigitalToRotateArray {
public static int getMinNumberInRotateArray(int[] number) {
if(number == null) {
return 0;
}
int pre = 0;
int rear = number.length -1;
int mid = pre;
while(number[pre] >= number[rear]) {
//当后一个数组的指针与前一个数组的指针距离相差为1时,即后一个数组指针指向的元素为最小值
if(rear - pre == 1) {
mid = rear;
break;
}
mid = (pre + rear) /2;
//如果下标为pre,rear和mid指向的三个数字相等,则只能顺序查找
if(number[pre] == number[rear] && number[pre] == number[mid]) {
return getMinInOrder(number, pre, rear);
}
if(number[mid] >= number[pre]) {
pre = mid;
}else if (number[mid] <= number[rear]) {
rear = mid;
}
}
return number[mid];
}
//按顺序查找最小值
public static int getMinInOrder(int[] number,int pre,int rear) {
int result = number[pre];
for (int i = pre+1; i <= rear; i++) {
if(result > number[i]) {
result = number[i];
}
}
return result;
}
public static void main(String[] args) {
// int[] number = {1,2,3,4,5};
int[] number1 = {1,0,1,1,1};
System.out.println(getMinNumberInRotateArray(number1));
System.out.println();
}
}