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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值