33.搜索旋转排序数组

在这里插入图片描述
就只想到了O(n)的,
想到的二分,

  1. target<nums[left] 则在右边有序搜索
  2. target>=nums[left],在左边有序搜素
  3. 自然是错误的,于是搁置不得了之。

看了题解恍然大悟。
以mid分成左右两个数组。
其中至少一个是有序的,且范围已知

  • 如果target在此范围内,二分即可
  • 不在此范围内,搜索另一个数组
class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        return searchHelp(nums,target,0,nums.length-1);
    }
    private int searchHelp(int[] nums,int target,int left,int right){
    
    
        if(left>right) return -1;
        int mid=left+((right-left)>>1);
        if(nums[mid]==target) return mid;
        if(mid-1>=left&&nums[left]<=nums[mid-1]){
    
    
            //有序在左边,且目标值在里面
            if(target>=nums[left]&&target<=nums[mid-1]){
    
    
                right=mid-1;
                while (left<=right){
    
    
                    mid=left+(right-left)/2;
                    if(nums[mid]==target) return mid;
                    if(nums[mid]>target) right=mid-1;
                    else left=mid+1;
                }
            }//不在里面,搜索右边无序的。
            return searchHelp(nums,target,mid+1,right);

        }else {
    
    
            //有序在右边,且目标在里面
            if(mid+1<nums.length&&target<=nums[right]&&target>=nums[mid+1]){
    
    
                left=mid+1;
                while (left<=right){
    
    
                    mid=left+(right-left)/2;
                    if(nums[mid]==target) return mid;
                    if(nums[mid]>target) right=mid-1;
                    else left=mid+1;
                }
            }
            return searchHelp(nums,target,left,mid-1);

        }
    }
}

还有一种更简洁的写法

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

关于判断

 if(mid-1>=left&&nums[left]<=nums[mid-1]){
    
    
 nums[left]<=nums[mid-1] 取等号,是为了考虑只有一个数的时候

猜你喜欢

转载自blog.csdn.net/qq_43179428/article/details/107126398
今日推荐