33. 搜索旋转排序数组

class Solution {
    public int search(int[] nums, int target) {
        int left = 0,right = nums.length - 1;
        int pos = -1;
        while(left < right){
            int mid = (left + right) / 2;
            if(mid == left){ //此时right = left + 1,可以跳出循环,单独判断nums[left]和nums[right】是否等于target
                break;
            }
            if(nums[mid] == target){
                pos = mid;
                break;
            }
            if(nums[left] < nums[mid]){
                if(nums[left] <= target && nums[mid] >= target)right = mid;
                else
                    left = mid;
                continue;
            }
            else if(nums[mid] < nums[right]){
                if(nums[mid] <= target && nums[right] >= target)left = mid;
                else
                    right = mid;
                continue;
            }
        }
        if(pos == -1){
            if(nums[left] == target)pos = left;
            else if(nums[right] == target)pos = right;
        }
        return pos;
    }
}

解题的思路基于一个事实,即将数组等分之后,至少有一侧是有序的,以下面的图来说明:

(绿线表示左侧的最小值要大于右侧的最大值)
在这里插入图片描述
在这里插入图片描述

数组划分不外乎这三种情况,可以看到每一种划分都至少有一侧是有序的。

求解步骤:

1、找到数组划分之后有序的那一半(例如nums[left] < nums[mid],则说明左侧有序),判断有序的这一侧的取值是否涵盖了target(例如,如果左侧是有序的,则判断是否有nums[left] <= target <= nums[mid])
2、(以左侧有序为例),如果nums[left] <= target <= nums[mid]成立,那么target只可能存在于左侧,因为右侧的取值范围是小于nums[left]或者大于nums[mid](参照图片中的绿线,并且注意nums无重复元素),这时就在左侧按正常的二分法来做
3、(以左侧有序为例),如果nums[left] <= target <= nums[mid]不成立,那么target只可能存在于右侧。有意思的来了,我们发现对于右侧的元素再进行对半分之后,产生的左右侧两个数组也满足至少有一个有序这个条件,于是又可以对右侧的这两个数组进行1-3的步骤。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值