题目
时间限制:4000ms
单点时限:1000ms
描述
输入一个递增排序的数组(元素不重复)的一个旋转(次数不详),找出某个元素.
输入
第一行:N,数组的长度
第二行:N个整数,作为数组的元素,空格分开
第三行:要查找的关键字K
输出
关键字K的下标,如果没有找到,输出-1
样例输入
5
6 1 2 3 4
1
样例输出
1
我的代码
解法一:二分法
import java.util.Scanner;
public class Exam11_FindInRotaryArr {
/**
* @param args
* 巧用二分法解题,可以先找出旋转数组最小值,
* 然后以最小值为轴,左右一定分别有序,在比较目标与数组尾元素的大小,判断在左还是右进行二分查找。
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int k = sc.nextInt();
int res = 0;
if (k == a[minIndex(a)]) {
res = minIndex(a);
}
// 在最小数左侧做二分查找
else if (k > a[a.length - 1]) {
res = binarySearch(a, 0, minIndex(a) - 1, k);
}
// 在最小数右侧做二分查找
else if (k <= a[a.length - 1]) {
res = binarySearch(a, minIndex(a) + 1, a.length - 1, k);
}
System.out.println(res);
}
private static int binarySearch(int[] a, int low, int high, int key) {
if (low > high) {
return -1;
}
// 防止溢出,移位也更高效
int mid = low + ((high - low) >> 1);
int midVal = a[mid];
if (midVal < key) {
return binarySearch(a, mid + 1, high, key);
} else if (midVal > key) {
return binarySearch(a, low, high - 1, key);
} else {
// key found
return mid;
}
}
private static int minIndex(int[] a) {
int begin = 0;
int end = a.length - 1;
// 考虑没有旋转这种特殊的旋转
if (a[begin] < a[end]) {
return a[begin];
}
// begin和end指向相邻元素,退出
while (begin + 1 < end) {
int mid = begin + ((end - begin) >> 1);
// 要么左侧有序,要么右侧有序
if (a[mid] >= a[begin]) {
begin = mid;
} else {
end = mid;
}
}
return a[end];
}
}
解法二:暴力搜索法
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [] arr = new int[n];
for(int i=0;i<n;i++) {
arr[i] = sc.nextInt();
}
int a = sc.nextInt();
sc.close();
for(int i=0;i<arr.length;i++) {
if(a==arr[i]) {
System.out.println(i);
return;
}
}
System.out.println(-1);
}
}