剑指offer 53-I 在排序数组中查找数字I (二分查找)

在这里插入图片描述

   这道题我们可以用暴力解决,使用数组或者HashMap来记录每个元素出现的次数。但是这题已经说了是排序数组,所以这样的时间复杂度就高。对于有顺序的查找,我们会想到二分。这个二分还是有点特别的,我们既要找target第一次出现的位置,还要找target最后一次出现的位置。
   初始化:左边界i=0,右边界j=nums.length-1
   循环二分:当闭区间[i,j]无元素时跳出
      1.计算中点mid=(left+right)/2
      2.①nums[mid]<target,则target在[mid+1,j]范围内
       ②nums[mid]>target,则target在[i.mid-1]区间内
       ③nums[mid]==target,则右边界right在闭区间[m+1,j]中,左边界left在闭区间[i,m-1]中
       若查找右边界right,则执行i=m+1(跳出时i指向右边界),若查找左边界left,则执行j=m-1(跳出是j指向左边界)

接下来我们就看看到底是怎么走的
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接下来就来看看代码
寻找右边界

        int i = 0, j = nums.length - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            if(nums[m] <= target) i = m + 1;
            else j = m - 1;
        }
        int right = i;

因为我们在上边分析的①和③已经知道,当nums[m]<target和nums[m]=target的时右边界,target的范围与右边界的范围是相等的,所以右边界的变化条件是<=。当跳出循环的时候,i就是右边界。

然后再提前判断下数组中有没有target

 if(j >= 0 && nums[j] != target) return 0;

因为如果存在target的话,刚跳出循环时的j就指向的target,所以如果j不指向target,则说明就没有找到。直接返回0。

寻找左边界

 	i = 0; j = nums.length - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            if(nums[m] < target) i = m + 1;
            else j = m - 1;
        }
        int left = j;

通过上边分析的②和③我们可以知道,nums[mid]>targe和nums[mid]==target
的时候,target的范围和左边界的范围是相等的,所以左边界的变化情况是>=。

最后得出结果:

 return right - left - 1;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值