Cracking the coding interview--Q9.3

原文:

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);
			}
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值