[LeetCode]Search in Rotated Sorted Array II

Question
Follow up for “Search in Rotated Sorted Array”:
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Write a function to determine if a given target is in the array.


本题难度Medium。

【复杂度】
时间 O(N) 空间 O(1)

【思路】
本题是Search in Rotated Sorted Array的变形。在Search in Rotated Sorted Array中可以通过nums[start]<=nums[mid]nums[mid]<=nums[end]判断两边是否为有序。但是在这里出现一个问题:比如左半边,如果nums[start]==nums[mid]它是有序吗?对于:

    [1 3 1 1 1]

左半边为1 3 1,符合条件但并不有序。不过如果nums[start]<nums[mid],那么左半边仍然是有序的。因此,我们列出三种情况进行处理:

  1. 左半边有序。如果target在左半边范围内就只搜索左半边,否则只搜索右半边
  2. 右半边有序。如果target在右半边范围内就只搜索右半边,否则只搜索左半边
  3. 都不是。两边都要分别搜索

其本质就是增加了对第三种情况的处理(29-34行)

【注意】

  1. 我们在判断是否为有序时,比如对于左半边是:nums[start]<nums[mid],不要写成nums[start]<nums[mid-1],这样有可能导致mid-1<0超过范围

  2. 在判断是否在其范围内,比如左半边是:nums[start]<=target&&target<nums[mid]不要写成target<nums[mid]只判断一边,例如:

     [4 5 6 1 2 3],target=3
    

    左半边为4 5 6,有序,而且3<6,但3不在左半边。而对于有序数列而言,如果target<nums[mid],target是不可能再出现在右半边,所以可以单边判断。

【代码】

public class Solution {
    public boolean search(int[] nums, int target) {
        //require
        int size=nums.length;
        if(size<1)
            return false;
        //invariant
        return helper(0,size-1,nums,target);
    }
    private boolean helper(int start,int end,int[] nums, int target){
        //base case
        if(end<start)
            return false;

        int mid=(start+end)/2;
        if(nums[mid]==target)
            return true;

        if(nums[start]<nums[mid]){
            if(nums[start]<=target&&target<nums[mid])
                return helper(start,mid-1,nums,target);
            else
                return helper(mid+1,end,nums,target);
        }else if(nums[mid]<nums[end]){
            if(nums[mid]<target&&target<=nums[end])
                return helper(mid+1,end,nums,target);
            else
                return helper(start,mid-1,nums,target);
        }else{
            if(helper(start,mid-1,nums,target))
                return true;
            else
                return helper(mid+1,end,nums,target);
        }
    }
}

参考

Java 1ms binary search solution with comments

public class Solution {
    public boolean search(int[] nums, int target) {
        // note here end is initialized to len instead of (len-1)
        int start = 0, end = nums.length;
        while (start < end) {
            int mid = (start + end) / 2;
            if (nums[mid] == target) return true;
            if (nums[mid] > nums[start]) { // nums[start..mid] is sorted
                // check if target in left half
                if (target < nums[mid] && target >= nums[start]) end = mid;
                else start = mid + 1;
            } else if (nums[mid] < nums[start]) { // nums[mid..end] is sorted
                // check if target in right half
                if (target > nums[mid] && target < nums[start]) start = mid + 1;
                else end = mid;
            } else { // have no idea about the array, but we can exclude nums[start] because nums[start] == nums[mid]
                start++;
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值