[leetcode 34.] 在排序数组中查找元素的第一个和最后一个位置


在这里插入图片描述

在这里插入图片描述

分析

看到排序数组,我们就可以用暴力法,直接从前向后遍历,但是这样的话,时间复杂度O(N),就不满足题中的O(logN)。
对于O(logN)的题目,我们就可以考虑二分法来解决这种问题。

然后我们把问题进行拆分,就可以看做是两个子问题。

  • 第一个就是找左边第一次出现的目标值位置,找不到就返回-1
  • 第二个就是找右边第一次出现目标值的位置,找不到就返回-1,注意这里左右两边返回的位置是可以相同的。

在此基础上,我们可以做一个优化,就是当左边第一次查找返回的目标位置为-1,也就是数组中没有该目标元素,我们就不需要第二次进行查找了,因为数组中就没有该元素,直接返回一个{-1,-1}的数组。

常见的二分法是这样的

左闭右闭区间 [left,right]

	while(left <= right)
	{
   
    	int  mid = (left + right)>>1;//找到中间节点的位置
        if(nums[mid] == target) return mid;
        else if(nums[mid] > target) right = mid - 1;//要找的元素在中间位置的左边,移动右边区间
        else if(nums[mid] < target) left = mid + 1;//要找的元素在中间位置的右边,移动左边区间
   }
   return -1;//没有找到返回-1
  • 为什么在没有找到的时候,转移方程是right = mid-1 left = mid + 1呢?

首先,我们的区间时左闭右闭的一个闭区间,也就是说我们的left 和 right两个下标位置我们要确定是有效的位置,这两个位置一定是没有查找的。
在每一次比较的时候,我们都是查找了mid这个中间位置 (这是一个有序数组)

  • nums[mid] > target :这种情况下,也就是我们需要查找的目标数据在mid位置的左边,并且mid位置我们已经找过了,但是没有结束,说明了当前mid位置不是目标数据,我们就需要移动right来缩小下一次我们查找时的区间大小,就得把right变成mid的前一个位置 mid - 1
  • nums[mid] < target:这种情况也就是我们需要查找的数据在mid位置的右边,我们就需要移动left的值来缩小下一次查找时区间的范围,所以说left就变成了mid的下一个位置 mid + 1

左闭右开区间 [left,right)

	while(left < right)
	{
   
    	int  mid = (left + right)>>1;
        if(nums[mid] == target) return mid;
        else if(nums[mid] > target) right = mid;
        else if(nums[mid] 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值