搜索区间

题目描述:给定一个包含 n 个整数的排序数组,找出给定目标值 target 的起始和结束位置。如果目标值不在数组中,则返回[-1, -1]

样例:给出[5, 7, 7, 8, 8, 10]和目标值target=8,返回[3, 4]


还记得在学习二分查找时遇到的第一个问题吗?要求返回目标值第一次在数组中出现的位置,详见:点击打开链接

那么现在问题就可以简化了:我们可以先通过二分法找到目标的任意一个位置,比如,在样例[5, 7, 7, 8, 8, 10]中8所在位置是3和4,我们找到任意一个位置(3或4)之后,在这一位将数组分割,例如,我们选择位于第3位的'8',将数组分割成[5, 7, 7, 8]和[8, 8, 10]两个部分,需要注意的是,两个数组都包含了我们选择的那个位,这样做的目的是防止其中一个数组完全不存在target.之后,再在向左边数组搜索target的第一个出现的位置,也就是target出现的区间的最左端的位置;在右边数组搜索target的最后一个出现的位置,也就是target出现的区间的最右端的位置。这两次查找都是二分法,其中,查找最左端位置的算法跟上面讲的那个问题一模一样,查找最右端位置的算法同理。

简单说,算法分为三步:

1. 二分法找到任意一个target

2. 以这个找到的target为分界线,将数组分成左右两部分

3. 分别查找左边数组最左端的target;右边数组最右端的target

代码照这个写就行:

class Solution:
    """
    @param A : a list of integers
    @param target : an integer to be searched
    @return : a list of length 2, [index1, index2]
    """
    def searchRange(self, A, target):
        left, right = 0, len(A) - 1
        result = []
        while left <= right:
            mid = (left + right) // 2
            if A[mid] == target:
                result.append(self.lower_bound(A, left, mid, target))
                result.append(self.upper_bound(A, mid, right, target))
                return result
            elif A[mid] > target:
                right = mid - 1
            else:
                left = mid + 1
        return [-1, -1]
    
    def lower_bound(self, array, left, right, target):
        left, right = 0, len(array) - 1
        while left <= right:
            mid = (left + right) // 2
            if array[mid] >= target:
                right = mid - 1
            else:
                left = mid + 1
        return left
    
    def upper_bound(self, array, left, right, target):
        left, right = 0, len(array) - 1
        while left <= right:
            mid = (left + right) // 2
            if array[mid] <= target:
                left = mid + 1
            else:
                right = mid - 1
        return right
        # write your code here
其中,lower_bound和upper_bound是分别向左右两边搜寻的函数,他们里面的形参left和right表示这两个数组的起止位置。由算法结构知:时间复杂度O(logn)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值