//评测题目:
// 本来是排序好的数组,随机选了一个pivot,rotate了一下
// 举例:
// pivot=8时:1 2 4 6 8 10 13 17 -> 8 10 13 17 1 2 4 6
// pivot=4时:1 2 4 6 8 10 13 17 -> 4 6 8 10 13 17 1 2
// 本来是排序好的数组,随机选了一个pivot,rotate了一下
// 举例:
// pivot=8时:1 2 4 6 8 10 13 17 -> 8 10 13 17 1 2 4 6
// pivot=4时:1 2 4 6 8 10 13 17 -> 4 6 8 10 13 17 1 2
// 设计一个算法快速找到给定的数字,返回所在的index
分析:rotate之后的数组是 先升序,然后从最大值降为最小值,最后再从最小值升序。
本题本质上还是一个折半查找。使用middle将数组折半,一半一定是升序的(可以用二分查找),另一半有可能是升序,也有可能和rotate之后的数组一样(递归)。
判断是否升序:arr[middle] >=arr[start] && arr[middle] <=arr[end]
public class PivoteQuestion {
public static void main(String[] args) {
int []arr = {6,8,10,13,17,1,2,4};
int len = arr.length;
int num = 2;
int result = pivotBinaryFind(arr, num, 0, len-1);
System.out.println(result);
}
public static int pivotBinaryFind(int []arr,int num,int start,int end){
if(start > end){
return -1;
}
int middle = (start + end)/2;
if(arr[middle] == num){
return middle;
}
if(arr[middle] >=arr[start] && arr[middle] <=arr[end]){//如果该段是升序的
return binarySearch(arr, num, start, end);
}else{//该段和原先解决的问题一样,先升序,然后降为最小值,再升序
int result = pivotBinaryFind(arr,num,start,middle-1);
return result==-1?pivotBinaryFind(arr,num,middle+1,end):result;
}
}
public static int binarySearch(int []arr,int num,int start,int end){
if(start > end){
return -1;
}
int middle = (start + end)/2;
if(arr[middle] == num){
return middle;
}else if(arr[middle] > num){
return binarySearch(arr,num,start,middle-1);
}else{
return binarySearch(arr,num,middle+1,end);
}
}
}