【LeetCode】解题81:Search in Rotated Sorted Array II

LeetCode解题 81:Search in Rotated Sorted Array II

Problem 81: Search in Rotated Sorted Array II [Medium]

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).

You are given a target value to search. If found in the array return true, otherwise return false.

Example 1:

Input: nums = [2,5,6,0,0,1,2], target = 0
Output: true

Example 2:

Input: nums = [2,5,6,0,0,1,2], target = 3
Output: false

Follow up:

  • This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates.
  • Would this affect the run-time complexity? How and why?

来源:LeetCode

解题思路

题解33:Search in Rotated Sorted Array类似。需要多考虑一种两个边界相等的情况,采用的办法是进行两次二分查找。

  • 基本思路是利用二分查找,除了边界相等的情况,其余每层递归都能排除掉一半的数值。
  • 难点在于条件判断,需要考虑要查找的target会不会因为排序数组的旋转而不在原本二分查找的那半段范围。为了方便说明,将头尾相接处称为断崖,二分点下标称为p,以下为需要分类讨论的情况:
    a. 假设nums[p] < target,说明目标值较大,正常情况下需要查找数组的右半部分,此时应有nums[right] > target,需要查找p+1 ~ right-1
    b. 当nums[right] < target时,与正常情况不同,是需要讨论的重点。按断崖所在的位置进行分类讨论。
    b1. 寻找断崖所处位置的方法是比较nums[right]nums[p]的值,如果nums[right] < nums[p],则说明断崖p ~ right之间,即最大的尾部处于这之间,要找的目标值比nums[p]大,就可以在p+1 ~ right-1之间查找。(例如在[4,5,6,7,8,9,1,2,3]中寻找9的第一次二分查找。)
    b2. 如果nums[right] > nums[p],则说明p ~ right之间是严格升序的,断崖应该在left ~ p之间,因此既比nums[p]大又比nums[right]大的目标值就应该在left ~ p-1之间查找。(例如在[7,8,9,1,2,3,4,5,6]中寻找9的第一次二分查找。)
    b3. 如果nums[right] = nums[p],那么无法判断出断崖left ~ p([7,8,9,1,2,2,2,2,2]中找9)还是在p ~ right([2,2,2,2,2,3,9,1,2]中找9),因为都有可能。这种情况下,需要对两半部分都进行二分查找,只有两边都返回false,才能证明数组中不存在target
    c. 上述数值比较过程中如果有正好相等的情况则之间返回下标即可。如果有left > right的情况则说明查找失败,返回false。
  • 数组个数为0或仅剩1个数且不为target时直接返回false。

极端情况下复杂度有可能为 O ( n ) O(n) O(n)

要点:二分查找条件判断

Solution (Java)

class Solution {
    public boolean search(int[] nums, int target) {
        int N = nums.length;
        if(N == 0) return false;
        return partSearch(nums, 0, N-1, target);
    }
    private boolean partSearch(int[] nums, int left, int right, int target){
        if(left > right) return false;
        if(left == right && nums[left] != target) return false;
        int p = (left + right) / 2;
        int nextl, nextr;
        if(nums[p] == target){
            return true;
        }
        else if(nums[p] < target){
            if(nums[right] == target){
                return true;
            }
            else if(nums[right] > target){
                return partSearch(nums, p+1, right-1, target);
            }
            else{
                if(nums[right] < nums[p]){
                	// 断崖在p~right之间
                    return partSearch(nums, p+1, right-1, target);
                }
                else if(nums[right] > nums[p]){
                	// 断崖在另半部分
                    return partSearch(nums, left, p-1, target);
                }
                else{ 
                    // 不能确定断崖位置,两半部分都要试
                    return partSearch(nums, left, p-1, target) || partSearch(nums, p+1, right-1, target);
                }
            }
        }
        else{
            if(nums[left] == target){
                return true;
            }
            else if(nums[left] < target){
                return partSearch(nums, left+1, p-1, target);
            }
            else{
                if(nums[left] > nums[p]){
                	// 断崖在left~p之间
                    return partSearch(nums, left+1, p-1, target);
                }
                else if(nums[left] < nums[p]){
                	// 断崖在另半部分
                    return partSearch(nums, p+1, right, target);
                }
                else{
                	// 不能确定断崖位置,两半部分都要试
                    return partSearch(nums, left+1, p-1, target) || partSearch(nums, p+1, right, target);
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值