原文:
Given a sorted array of n integers that has been rotated an unknown number of times, give an O(log n) algorithm that finds an element in the array. You may assume that the array was originally sorted in increasing order.
EXAMPLE:
Input: find 5 in array (15 16 19 20 25 1 3 4 5 7 10 14)
Output: 8 (the index of 5 in the array)
译文:
一个数组有n个整数,它们排好序(假设为升序)但被旋转了未知次, 即每次把最右边的数放到最左边。给出一个O(log n)的算法找到特定的某个元素。
例子:
输入:在数组(15 16 19 20 25 1 3 4 5 7 10 14)中找出5
输出:8(5在数组中的下标)
题目中提到了几个关键的词:有序,O(log n)。我们马上能联想到的就是二分查找算法。 但简单的二分查找肯定不行,因为这个数组被旋转了。也就是该数组前面一段有序, 后面一段有序,且前面那段的数要大于等于后面那段的数(本题考虑递增序列,递减同理)。 因此,我们需要对二分查找算法做一下修改,来解决这个具体的问题。
package chapter_9_SortingandSearching;
import java.util.Scanner;
/**
*
* 一个数组有n个整数,它们排好序(假设为升序)但被旋转了未知次, 即每次把最右边的数放到最左边。给出一个O(log n)的算法找到特定的某个元素。
*
*/
public class Question_9_3 {
/**
* @param array
* @param find
* @return
*
* 数组旋转之后,前半段后半段都是各自连续的,并且前半段数组必定大于后半段
* 二分查找进行修改,每次判断中间位置元素mid
* 如果array[mid] >= array[start] 说明前半段是连续的,
* 则此时可以判断(array[mid] > find && array[start] <= find) 属于前半段
* 否则在后半段
* 否则判断后半段是否连续
* 同理
*
*/
public static int findIndex(int array[], int find) {
int start = 0;
int end = array.length - 1;
while(start <= end) {
int mid = (start + end) / 2;
// mid如果不是需要找的,概率比找到要大,所以if先执行
if(array[mid] != find) {
// 其中mid左右之一必定是连续的
if(array[mid] >= array[start]) {
// 如果左边是连续的
if((array[mid] > find && array[start] <= find)) {
end = mid -1;
} else {
start = mid + 1;
}
} else {
// 右边是连续的
if(array[mid] < find && array[end] >= find) {
start = mid + 1;
} else {
end = mid -1;
}
}
} else {
return mid;
}
}
return -1;
}
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
scanner.nextLine();
while(num -- > 0) {
String str = scanner.nextLine();
String[] strs = str.split(" ");
int[] array = new int[strs.length-1];
for(int i=0; i<strs.length-1; i++) {
array[i] = Integer.parseInt(strs[i]);
}
int find = Integer.parseInt(strs[strs.length-1]);
int index= findIndex(array, find);
if(index == -1) {
System.out.println("connot find it!");
} else {
System.out.println("index:" + index);
}
}
}
}