33.搜索旋转排序数组(java)

33.搜索旋转排序数组

题目描述

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1


解法:二分搜索

第一类 2 3 4 5 6 7 1 这种,也就是 nums[start] <= nums[mid]。此例子中就是 2 <= 5。
这种情况下,前半部分有序。因此如果 nums[start] <=target 第二类 6 7 1 2 3 4 5 这种,也就是 nums[start] > nums[mid]。此例子中就是 6 > 2。
这种情况下,后半部分有序。因此如果 nums[mid]

33.搜索旋转排序数组(java)_第1张图片

class Solution {
    public int search(int[] nums, int target) {
        if(nums.length==0) return -1;
        int pivot=nums[0];
        int lo=0,hi=nums.length-1,index=-1;
        while(lo<=hi){
            int mid=lo+(hi-lo)/2;
            if(nums[mid]==target){
                return mid;
            }
            //加上等于号是为了只剩两个数的时候,相等,匹配前者,从target>=pivot可用体现
            if(nums[mid]>=pivot){
                if(target>=pivot&&target<nums[mid]){
                    hi=mid-1;
                }
                else{
                    lo=mid+1;
                }
            }
            else{
                if(target<pivot&&target>nums[mid]){
                    lo=mid+1;
                }
                else{
                    hi=mid-1;
                }
            }
        }
        return -1;
    }
}

33.搜索旋转排序数组(java)_第2张图片

代码优化

分析:

简要来说:

  • nums[0] <= nums[mid](0 - mid不包含旋转)且nums[0] <= target <= nums[mid] 时 high 向前规约;

  • nums[mid] < nums[0](0 - mid包含旋转),target <= nums[mid] <= nums[0] 时向前规约(target 在旋转位置到 mid 之间)

  • nums[mid] < nums[0]nums[mid] <= nums[0] <= target 时向前规约(target 在 0 到旋转位置之间)

其他情况向后规约

即总结如下

nums[0] <= target <= nums[i]
target <= nums[i] <= nums[0]
nums[i] <= nums[0] <= target

(nums[0] <= target), (target <= nums[i]) ,(nums[i] <= nums[0]),现在我们想知道这三项中有哪两项为真(明显这三项不可能均为真或均为假(因为这三项可能已经包含了所有情况))

class Solution {
    public int search(int[] nums, int target) {
        if(nums.length==0) return -1;
        int pivot=nums[0];
        int lo=0,hi=nums.length-1,index=-1;
        while(lo<=hi){
            int mid=lo+(hi-lo)/2;
            if(nums[mid]==target){
                return mid;
            }
            //最后一条需要加=  处理[1,3] 3的用例
            if((nums[0] <= target)^ (target <= nums[mid])^(nums[mid] >= nums[0])){
                hi=mid-1;
            }
            else{
                lo=mid+1;
            }
        }
        return -1;
    }
}

33.搜索旋转排序数组(java)_第3张图片

你可能感兴趣的:(leecode)