import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/** * 给定一个旋转数组(即,原来有序的数组,把前面某一部分放到数组的末尾,形成两部分有序子数组)
* 在数组中查找某一值n ,返回它的位置。不存在返回Null
*@author YunXing
* 旋转数组的特例:有序数组本身(把数组前0项放到数组末尾)。
* * 思路:利用数组部分有序的特性,进行二分查找。不过要注意的是,在二分时,要先确定中间位置mid是在第一部分有序子数组中;
还是在第二部分有序子数组中,然后才好确定left/right如何移动。
还有特殊情况就是,如果给定的旋转数组的 left, mid, right 下标指向的元素都相等,
那么二分查找时,就无法确定left、right如何移动,只好用顺序查找的方法。
如:2 0 1 2 2 2 2 */
public class RotatingArray {
public static void main(String[] args) {
BufferedReader bufIn = null;
try {
bufIn = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line= bufIn.readLine()) != null) {
int n = Integer.parseInt(line);
int[] rotateArr = new int[5];
for (int i = 0; i < rotateArr.length; i++) {
rotateArr[i] = Integer.parseInt(bufIn.readLine());
}
int index = divideSearch(rotateArr, n);
if(index == -1)
System.out.println("NULL");
else
System.out.println("Founded index: " + index + ", value:" + rotateArr[index]);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {try {
if(bufIn != null) bufIn.close();
} catch (Exception e2) {}
}
}
/** * 旋转数组二分查找
* @param rotateArr
* @param n
* @return
* 4 5 6 7 1 2 3
*/
private static int divideSearch(int[] rotateArr, int n) {
int left = 0;
int right = rotateArr.length - 1;
int mid = 0;
while(left <= right) {
mid = (left + right) / 2;
//如果前后的元素和中间的元素都相等,就无法确定mid是前面部分子数组,
// 还是后面部分的。只能用顺序查找。
if(rotateArr[left] == rotateArr[mid] && rotateArr[mid] == rotateArr[right])
return inOrderSearch(rotateArr, n);
if(rotateArr[mid] == n)
return mid;
if(rotateArr[mid] >= rotateArr[left]) {
//mid在第一部分子数组(有序)
if(n > rotateArr[mid])
left = mid+1;
else
right = mid;
} else if (rotateArr[mid] <= rotateArr[right]) {
//mid在第2部分子数组(有序)
if(n < rotateArr[mid])
right = mid-1;
else
left = mid;
}
}
return -1;
}
private static int inOrderSearch(int[] rotateArr, int n) {
System.out.println("顺序查找::::");
int index = -1;
for (int i = 0; i < rotateArr.length; i++) {
if(rotateArr[i] == n) {
index = i;break;
}
}
return index;
}
}