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.

两次二分,一次找到rotate的位置,一次找target。

就是说,排序数组可能是右移了一定位数。让你在这个数组中找一个target值。当然用线性查找就没意义了。

想这个解法需要头脑比较清晰。记得原来高中做题,老师最常说的一句话是啥?”要揣摩出题人意图啊“。。。这道题也是这样的。如果是在一个有序数组里面找一个值,那么一般都是用binarySearch。现在数组变了,(当然,还保持一些其他特点,我们下面说),能不能用binarySearch呢,或者我们改一下binarySearch呢?

如果用binarySearch,我们在通过Low和High序号得到Mid以后,应该如何剔除一半的数据呢?

下面是rotate后的一个有序数组的图。四边形的斜边表示数组中数值的大小。

在这种情况下数组分了两部分,分别都是有序(递增)的。

当我们计算了Mid以后,有两种可能,分别用Mid1和Mid2表示。

1. 如果A[Low] < A[Mid],说明Mid落在区间1中,即图中Mid1的位置。那么,如果target小于A[Mid1],那么继续在Low和Mid1中间搜索;否则,在Mid1和High中间搜索;

2. 如果A[Low] >= A[Mid],说明Mid落在区间2中,即图中Mid2的位置。同理,如果target小于A[Mid2],那么继续在Low和Mid2中间搜索;否则,在Mid2和High中间搜索。

这样,平均地,我们每次剔除一半数据,时间复杂度是O(logn)。

代码如下:

 1 public class Solution {
 2     public int search(int[] A, int target) {
 3         // Note: The Solution object is instantiated only once and is reused by each test case.
 4         //first divide find that point rotated, second one find that value
 5         assert(A!=null);
 6         int start = 0, 
 7         end = A.length-1;
 8         while(start<=end){
 9             int mid = (start+end)/2;
10             if(A[mid]==target)
11                 return mid;
12             if(A[mid]>target && (A[end]>A[mid] || A[end]<target) 
13                 || A[mid]<target && A[end]>A[mid] && A[end]<target){
14                     end=mid-1;
15             }else{
16                 start=mid+1;
17             }
18         }
19         return -1;
20     }
21 }

 第二遍:

分类的方式很特别:

这里是按某一部分是不是sorted 来分的。

如果start < mid, 说明左边是sorted,那么 若 target 落在这个区间内 则 end = mid - 1;

如果不是,说明右边是sorted,那么若target 落在这个区间内 则 start = mid + 1;

 1 public class Solution {
 2     public int search(int[] A, int target) {
 3         // Note: The Solution object is instantiated only once and is reused by each test case.
 4         //first divide find that point rotated, second one find that value
 5         int end = A.length - 1;
 6         int start = 0;
 7         while(start <= end){
 8             int mid = (end + start) / 2;
 9             if(target == A[mid]) return mid;
10             if(A[start] <= A[mid]){//left half is sorted
11                 if(A[start] <= target &&  target < A[mid]) end = mid - 1;
12                 else start = mid + 1;
13             }
14             else{
15                 if(A[mid] < target && target <= A[end]) start = mid + 1;
16                 else end = mid - 1;
17             }
18         }
19         return -1;
20     }
21 }
原文地址:https://www.cnblogs.com/reynold-lei/p/3366298.html