Fork me on GitHub

【数据结构】算法 搜索旋转排序数组 Search in Rotated Sorted Array II

搜索旋转排序数组 Search in Rotated Sorted Array II

There is an integer array nums sorted in non-decreasing order (not necessarily with distinct values).

Before being passed to your function, nums is rotated at an unknown pivot index k (0 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,4,4,5,6,6,7] might be rotated at pivot index 5 and become [4,5,6,6,7,0,1,2,4,4].

Given the array nums after the rotation and an integer target, return true if target is in nums, or false if it is not in nums.

就是有一个按非降序排列的整数数组nums,在传给函数之前,nums在下标k上做了旋转,上面有个例子,然后判断一个整数target是否存在于数组中,如果存在target返回true

nums = [2,5,6,0,0,1,2], target = 0
true
nums = [2,5,6,0,0,1,2], target = 3
false

思路

首先查找元素这个事,暴力点就是从头找,这个肯定不考虑了,会for的都会写。

其实nums 没有旋转之前,它是一个非降序排列的,我们可以使用二分来查找。但是旋转后,nums就不再严格是一个非降序排列的数组。它会变成一个类似锯齿形的排列,也就是说它的单调性会变成2段。

假设nums1,nums2是旋转后的2段。

可能出现的情况:

1 nums1的前一部分,nums2的后一部分和target相等,这个情况下直接返回true

2如果不相等,那就先将两端相同的元素剔除,剩下的nums1的首元素一定比nums2的尾元素要大。

假设nums1的首元素为head,nums2的尾元素为tail

在这个情况下,

情况a: 当nums[mid]<=tail,那么说明此时mid一定落在nums2的区间内;

情况b: 当nums[mid]>tail,那么说明此时mid一定落在nums1的区间内;

当情况a下,nums[mid]<target<=nums[tail],说明如果存在target,那么一定在nums2区间的后半段内并且满足target下标属于(mid,tail]此时的head要调整到mid+1,此时可以使用二分;但是如果target不属于

(mid,tail],此时就要调整tail到mid-1;

当情况b下,nums[head]<=target<nums[mid],说明如果存在target,那么一定在nums1区间的前半段并且满足target下标属于(head,mid),此时调整tail到mid,此时可以使用二分;否则target可能存在于nums1后面直到tail,调整head到mid+1;

不管二分如何调整head tail,都是为了将target包含在[head,tail]内。

public boolean search(int[] nums, int target) {
        if(nums[0]==target||nums[nums.length-1]==target){
            return true;
        }
        int l = 0;
        int r = nums.length -1;
        int mid,head,tail;
        while(l<nums.length&&nums[l]==nums[0]){
            ++l;
        }
        while(r>=0&&nums[r]==nums[0]){
            --r;
        }
        head = l;
        tail = r;
        while(l<=r){
            mid= (l+r)>>1;
            if(nums[mid]==target){
                return true;
            }
            if (nums[mid]<=nums[tail]){
                if (nums[mid]<target&&target<=nums[tail]){
                    l = mid+1;
                }
                else{
                    r = mid -1;
                }
            }
            else{
                if (nums[mid]>target&&nums[head]<=target){
                    r = mid-1;
                }
                else{
                    l = mid +1;
                }
            }
        }
        return false;
    }

Tag

binary search

posted @ 2021-10-14 20:55  WilliamCui  阅读(35)  评论(0编辑  收藏  举报