https://leetcode.com/problems/search-in-rotated-sorted-array/
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
解题思路:
这时一道二分查找题,与标准的binary search不同,它的数组没有排序,在某个位置被rotate了。所以我们无法直接A[mid]的值和target的大小直接用mid去更新start或者end,但是一定有方法,我们来看看。
例如一个A[]:6 7 0 1 2 4 5,mid为1。如果我们要搜1,这种情况下target<A[mid],一定在前半段。如果要找比A[mid]大的,就不一定了,有可能在后半段,也有可能在被rotate到前面去的几个(6、7)里面。那么如何判断到底在前面还是后面?就看target和A[end]也就是5的大小,如果>5,一定是被rotate到前面去的,就在前面,否在在后半段。
这样就清楚了。可是写出来出错,为什么?
考虑另一个例子,A[]:2 4 5 6 7 0 1,这种情况被rotated到前面的元素多,mid为6。这时的判断就完全相反了,比A[mid]大的,一定在后半段,但是比A[mid]小的,要和A[start]比大小,然后看到底在前半段还是后半段。
这里我们可以看到,要先根据A[mid]和与[start]或者A[end]的大小来分别讨论,但是整体思路还是比较清晰的。题目不是太难。
public class Solution { public int search(int[] A, int target) { int start = 0; int end = A.length - 1; while(start <= end){ int mid = (start + end) / 2; if(target == A[mid]){ return mid; } if(A[mid] < A[start]){ //后半段一定比mid大,所以这时target一定在前面 if(target < A[mid]){ end = mid - 1; } //有可能在后半段,也有可能在rotate到前面的那部分 if(target > A[mid]){ if(target <= A[end]){ start = mid + 1; }else{ end = mid - 1; } } }else{ //前半段一定比mid小,所以这时target一定在后面 if(target > A[mid]){ start = mid + 1; } if(target < A[mid]){ if(target < A[start]){ start = mid + 1; }else{ end = mid - 1; } } } } return -1; } }
update 2015/07/12:
更新了代码,先判断target是不是在有序的那段,否则就在另一段
public class Solution { public int search(int[] nums, int target) { if(nums.length == 0) { return -1; } int start = 0, end = nums.length - 1; while(start <= end) { int mid = (start + end) / 2; if(nums[mid] == target) { return mid; } // 必须是小于等于,因为start可能等于mid if(nums[start] <= nums[mid]) { if(target < nums[mid] && target >= nums[start]) { end = mid - 1; } else { start = mid + 1; } } else { if(target > nums[mid] && target <= nums[end]) { start = mid + 1; } else { end = mid - 1; } } } return -1; } }