【局部有序】的【二分查找】

题目

给定一个局部有序的数组,所谓局部有序指:将一个升序排序的数组循环右移若干次。
在数组中寻找目标值 t 的索引,若存在返回其索引,不存在返回-1。

例如:
a=[4,5,6,7,0,1,2],t=1

结果为5

分析

一个升序排序的数组循环右移若干次后有两种情况
情况1:还是一个升序数组。
情况2:数组被分为两部分,这两部分分别升序。例如示例中的[4,5,6,7,0,1,2],可以分为两个部分[4,5,6,7]和[0,1,2],两部分各自保持升序。

一看到有关检索有序区间,大家肯定会想到二分查找。
情况1,就是朴素的二分便可,所以接下来主要分析情况2。
当我们对情况2进行二分之后,会发现有两种可能性:

1.左边有序
请添加图片描述
这个时候很明显,如果目标值t大于等于左边界且小于中间值,则二分取左半部分,否则取右半部分。

2.右边有序
请添加图片描述
这个时候很明显,如果目标值t大于中间值且小于等于有边界,则二分取右半部分,否则取左半部分。

那么如何区分左边有序和右边有序呢?这很简单。
拿情况2举例:如果左边界的值大于中间值,说明右半部分是有序的。

讨论完了这种局部有序的情况,会发现,全局有序的时候用这种方式二分也是可以的,所以我们们就可以直接用这种方式处理这个题目了。

代码

public int search(int[] nums, int target) {
    int l=0,r=nums.length-1,m,t=target;
    while(l<=r){
        m=l+(r-l>>1);
        if(target==nums[m]){
            return m;
        }else if(nums[l]>nums[m]){//右边有序
            if(t>nums[m]&&t<=nums[r]){//答案在右边
                l=m+1;
            }else{
                r=m-1;
            }
        }else{//左边有序
            if(t<nums[m]&&t>=nums[l]){//答案在左边
                r=m-1;
            }else{
                l=m+1;
            }
        }
    }
    return -1;
}

题目链接
传送门

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值