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

中等难度的题目,

cccd6dd33cc8b20f8b05466535d16fef.png

第一想法其实很简单,就是循环遍历,记录数组

中等于
的元素的下标,然后直接返回第一个和最后一个下标。
if target not in nums:

这是在判断

是否在数组
里,如果不存在就直接返回

代码:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if target not in nums:
            return [-1, -1]
        res = []
        for i in range(len(nums)):
            if nums[i] == target:
                res.append(i)
        return [res[0], res[-1]]

但是显然这段代码的时间复杂度并不是

。于是,采用二分思想解题。

关于二分查找的算法详解,可以看这篇文章:

力扣​leetcode-cn.com

在有序数组中查找元素肯定使用二分法,二分法的核心思想是“夹逼法”或“排除法”,是“减而治之”算法思想的体现。

  1. 尽最大可能排除不符合题意的元素,在每一轮循环中不断减少候选区间的范围,直到候选区间收缩成 1 个数。
  2. 因为数组中很可能不存在目标值,因此在第 1 步使用“排除法”最后剩下的这个数,再判断一下它是否等于
    即可。

对于这个问题,我们其实可以拆分成两个问题,分别来解决。

  1. 开始位置:找到等于
    的第一个元素索引,如果找不到等于
    的数,则返回-1。如果小于,肯定不是解,此时
  2. 结束位置:找到等于
    的最后一个个元素索引,如果找不到等于
    的数,则返回-1。如果大于,肯定不是解,此时

下面给出的参考代码:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        size = len(nums)
        if size == 0:
            return [-1, -1]
        num1 = self.__lower_bound(nums, target)
        if num1 == -1:
            return [-1, -1]
        num2 = self.__upper_bound(nums, target)
        return [num1, num2]
    
    def __lower_bound(self, nums, target):
        left, right = 0, len(nums) - 1
        while left < right:
            # mid = left + (right - left) // 2
            mid = (left + right) >> 1
            if nums[mid] < target:
                left = mid + 1
            else:
                right = mid
        if nums[left] != target:
            return -1
        return left
    
    def __upper_bound(self, nums, target):
        left, right = 0, len(nums) - 1
        while left < right:
            # mid = left + (right - left + 1) // 2
            mid = (left + right + 1) >> 1
            if nums[mid] > target:
                right = mid - 1
            else:
                left = mid
        if nums[left] != target:
            return -1
        return left

代码中我把

mid = left + (right - left) // 2

以及

mid = left + (right - left) // 2

改成

mid = (left + right) >> 1

mid = (left + right + 1) >> 1

的原因是参照这篇文章:

力扣​leetcode-cn.com

另外,这篇文章的作者也写了一篇《十分好用的二分查找法模板》,可以看一下。

力扣​leetcode-cn.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值