Search in Rotated Sorted Array (Java)

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.

這道題由於存在將有序數組進行了翻轉,二分查找方法就不能直接用了,必須將其變化纔可以正常使用,二分搜索的重點是判斷到底是應該向前找還是向後找。像這道題就存在這樣的問題,在全局low和high之中,數列是非有序的,而在某個局部low和high之間,數列很可能是有序的。所以首先需要一個判斷條件 是否A[low] < A[high],如果小於則是有序,如果大於則是無序。

其次,判斷找target的下一次二分位置是在前半段還是後半段。比如找6,不能只比較6和A[mid]的大小,因爲A[mid] = 7,而7的前半段和後半段都是小於7的數,這時候需要將target和A[high]比較以及A[mid]和A[high]比較。當 targe < A[mid]時,如果A[mid]>A[high](拐點在右邊)且target<=A[high](沒翻轉時target在拐點前半段)且A[low] > A[high](本段無序),就往後找,其他情況往前找。同理,target > A[mid]時,A[mid]<A[high](拐點在左邊)且target>A[high](沒翻轉時target在拐點後半段)且A[low]>A[high](本段無序),就往前找,其他情況往後找。

Source1

public class Solution {
    public int search(int[] A, int target) {
        return BinarySearch(0, A.length - 1, A, target);
    }
    
    public int BinarySearch(int low, int high, int[] A, int target){
    	while(low <= high){
    		int mid = low + ((high - low) >> 1);
    		if(A[mid] > target){
    			if(A[high] < A[low] && target <= A[high] && A[mid] > A[high]){
    				low = mid + 1;
    			}
 
    			else high = mid - 1;
    		}
    		else if(A[mid] < target){
    			if(A[high] < A[low] && target > A[high] && A[mid] < A[high]){
    				high = mid - 1;
    			}
    			else low = mid + 1;
    		}
    		else return mid;
    	}
    	return -1;
    }
}


還有一種方法是用mid和low比,如果mid > low 證明左半部分有序,如果mid < low 證明右半部分有序,如果mid == low,此時的二分局部區間要麼只剩一個元素,要麼剩兩個元素,在if之前就先判斷了target是否與A[mid]相等,所以這裏的else語句只需要使low++。

Test

    public static void main(String[] args){
    	int[] A = {4, 5, 6, 7, 0, 1, 2};
    	System.out.println(new Solution().search(A, 6));
  
    }


Source2

    public int search(int[] A, int target) {
        int low = 0, high = A.length - 1;
        while(low <= high){
        	int mid = low + ((high - low) >> 1);
        	if(target == A[mid]) return mid;
        	if(A[low] < A[mid]){  //左半部有序
        		if(A[low] <= target && target < A[mid]){
        			high = mid - 1;
        		}
        		else low = mid + 1;
        	}
        	else if(A[low] > A[mid]){ //右半有序
        		if(A[high] >= target && target > A[mid]){
        			low = mid + 1;
        		}
        		else high = mid - 1;
        	}
        	else low ++;  // A[low] == A[mid] 只有兩種情況 要麼該局部區間一個值 要麼該局部區間兩個值
        }
        return -1;
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章