题解|旋转数组中的二分查找

题解|旋转数组中的二分查找

描述
输入一个递增排序的数组(元素不重复)的一个旋转(次数不详),找出某个元素.

输入
第一行:N,数组的长度
第二行:N个整数,作为数组的元素,空格分开
第三行:要查找的关键字K

输出
关键字K的下标,如果没有找到,输出-1

样例输入

5
6 1 2 3 4
1

样例输出

1

思路
O(n)的算法不写了,下面是O(lgn)的。
在旋转数组中先找到最小的一个元素位置,例如[7,9,1,3,5]中的1。先判断目标数字是否等于最小数字,再比较目标数字k与arr[end]的大小,确定应该在最小数字的左侧进行二分查找还是右侧进行二分查找。

import java.util.Scanner;

public class FindInRotaryArr {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			int ans = -1;
			int n = sc.nextInt();
			int[] arr = new int[n];
			for (int i = 0; i < arr.length; i++) {
				arr[i] = sc.nextInt();
			}
			int k = sc.nextInt();
			int indexOfMin = f(arr);
			if (k == arr[indexOfMin]) {
				ans = indexOfMin;
			}
			int end = arr.length - 1;
			if (k > arr[end]) {// 在[begin,indexOfMin - 1]
				int begin = 0;
				end = indexOfMin - 1;
				ans = binarySearch(arr, begin, end, k);
			} else if (k < arr[end]) {
				int begin = indexOfMin;
				ans = binarySearch(arr, begin, end, k);
			} else {
				ans = end;
			}
			System.out.println(ans);
		}
	}

	private static int binarySearch(int[] arr, int begin, int end, int k) {
		while (begin <= end) {
			int mid = (begin + end) / 2;
			if (k > arr[mid]) {
				begin = mid + 1;
			} else if (k < arr[mid]) {
				end = mid - 1;
			} else {
				return mid;
			}
		}
		return -1;
	}

	// 返回数组中最小数字的索引
	private static int f(int[] arr) {
		int begin = 0;
		int end = arr.length - 1;
		// 考虑数组没有旋转的特殊情况
		if (arr[end] > arr[begin]) {
			return begin;
		}
		// 当只剩两个数字进行二分查找时,右边的数字一定是最小值
		while (begin + 1 < end) {
			int mid = (begin + end) / 2;
			if (arr[mid] < arr[end]) {// 右侧有序
				end = mid;
			} else {
				begin = mid;
			}
		}
		return end;
	}
}

猜你喜欢

转载自blog.csdn.net/a739260008/article/details/86554665