题目:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{ 3,4,5,1,2 }为{ 1,2,3,4,5 }的一个旋转,该数组的最小值为1。
算法思想:
本题给出的数组在一定程度上是排序的,因此可以用二分查找的思想来解决问题。
1.定义两个指针分别指向数组的第一个元素和最后一个元素。根据旋转的规则,得知第一个元素应该大于或者等于最后一个元素。
2.找到中间元素,如果比左指针元素大,那么最小元素在右边,将左指针移到中间,继续查找;如果比左指针元素小,那么最小元素在左边(含该元素),将右指针移到中间,继续查找;
3.直到两个指针临近,左指针位于前面递增子数组的最后一个元素,指向最大元素;右指针位于后面递增子数组的第一个元素,指向最小元素。
(特例,如果左、右指针指向的元素与中间元素的值都相同,只能按顺序查找)
代码实现:
public int rotateArrMin(int[] arr) {
if(arr == null || arr.length <= 0) //非空判断
throw new RuntimeException("Invalid Input");
//定义左、右指针
int left = 0;
int right = arr.length-1;
int middle;
while(left < right) {
if(right - left == 1) //两个指针临近,找到最小元素
return arr[right];
middle = (left + right)/2; //确定中间位置
if(arr[left] == arr[middle] && arr[right] == arr[middle]) //左、中、右三值相同时,顺序查找
return minInorder(arr,left,right);
else if(arr[middle] >= arr[left]) //中间元素大于等于左指针元素,左指针移到中间
left = middle;
else //否则,右指针移到中间
right = middle;
}
return 0;
}
private int minInorder(int[] arr, int left, int right) {
int min = arr[left];
for(int i = left +1; i <= right; i++) {
if(min > arr[i])
min = arr[i];
}
return min;
}