【Leetcode刷题Python】34. 在排序数组中查找元素的第一个和最后一个位置(二分查找)

简介: 解决LeetCode "在排序数组中查找元素的第一个和最后一个位置" 问题的方法。第一种方法是使用两次二分查找,首先找到目标值的最左边界,然后找到最右边界。第二种方法是利用Python的list.index()方法,先正序找到起始位置,再逆序找到结束位置,并给出了两种方法的Python实现代码。

1 题目

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8

输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6

输出:[-1,-1]

2 解析

(1)方法一

两次二分查找

第一次查找起始位置:

1、二分的范围,l = 0l=0, r = nums.size() - 1r=nums.size()−1,我们去二分查找>=target>=target的最左边界。

2、当nums[mid] >= targetnums[mid]>=target时,往左半区域找,r = midr=mid。

3、当nums[mid] < targetnums[mid]<target时, 往右半区域找,l = mid + 1l=mid+1。

4、如果nums[r] != targetnums[r]!=target,说明数组中不存在目标值 targettarget,返回 [-1, -1][−1,−1]。否则我们就找到了第一个>=target>=target的位置LL。

第二次查找结束位置:

1、二分的范围,l = 0l=0, r = nums.size() - 1r=nums.size()−1,我们去二分查找<=target<=target的最右边界。

2、当nums[mid] <= targetnums[mid]<=target时,往右半区域找,l = midl=mid。

3、当nums[mid] > targetnums[mid]>target时, 往左半区域找,r = mid - 1r=mid−1。

4、找到了最后一个<=target<=target的位置RR,返回区间[L,R][L,R]即可。


二分查找的模板及使用方法

模板1

当我们将区间[l, r][l,r]划分成[l, mid][l,mid]和[mid + 1, r][mid+1,r]时,其更新操作是r = midr=mid或者l = mid + 1l=mid+1,计算midmid时不需要加11,即mid = (l + r)/2mid=(l+r)/2。

代码模板:

def bsearch_1( l,  r):
   while (l < r)
      mid = (l + r)/2;
      if (check(mid)):
          r = mid
      else:
          l = mid + 1;   
   return l;

模板2

当我们将区间[l, r][l,r]划分成[l, mid - 1][l,mid−1]和[mid, r][mid,r]时,其更新操作是r = mid - 1r=mid−1或者l = midl=mid,此时为了防止死循环,计算midmid时需要加11,即mid = ( l + r + 1 ) /2mid=(l+r+1)/2。

代码模板:

def bsearch_2( l,  r)
   while (l < r)
      mid = ( l + r + 1 ) /2
      if (check(mid)): 
          l = mid;
      else:
          r = mid - 1;
   return l;

(2)方法二

利用Python的返回索引的方法list.index()

第一次正序,第二次逆序

3 Python实现

(1)方法一

def searchRange(self, nums: List[int], target: int) -> List[int]:
        # 方法一:两个二分查找
        if target not in nums:
            return [-1,-1]
        l = 0
        r = len(nums)-1
        while l<r:
            mid = int((l+r)/2)
            if nums[mid]>=target:
                r = mid
            else :
                l = mid+1
        if nums[r] !=target:return [-1,-1]
        L  = l
        l,r = 0,len(nums)-1
        while l < r:
            mid = int((l+r+1)/2)
            if nums[mid] <= target:
                l = mid
            else:
                r = mid-1        
        return [L,r]

(2)方法二

def searchRange(self, nums: List[int], target: int) -> List[int]:
        # 方法二:两次顺序遍历
         if target not in nums:
             return [-1,-1]
         start = nums.index(target)
         nums.reverse()
         end = len(nums)-nums.index(target)-1
         return [start,end]
目录
相关文章
|
9天前
|
搜索推荐 Python
快速排序的 Python 实践:从原理到优化,打造你的排序利器!
本文介绍了 Python 中的快速排序算法,从基本原理、实现代码到优化方法进行了详细探讨。快速排序采用分治策略,通过选择基准元素将数组分为两部分,递归排序。文章还对比了快速排序与冒泡排序的性能,展示了优化前后快速排序的差异。通过这些分析,帮助读者理解快速排序的优势及优化的重要性,从而在实际应用中选择合适的排序算法和优化策略,提升程序性能。
23 1
|
1月前
|
机器学习/深度学习 并行计算 大数据
【Python篇】NumPy完整指南(上篇):掌握数组、矩阵与高效计算的核心技巧2
【Python篇】NumPy完整指南(上篇):掌握数组、矩阵与高效计算的核心技巧
69 10
|
1月前
|
索引 Python
【Python篇】NumPy完整指南(上篇):掌握数组、矩阵与高效计算的核心技巧1
【Python篇】NumPy完整指南(上篇):掌握数组、矩阵与高效计算的核心技巧
85 4
|
2月前
|
Python
Python 选出列表中特定的元素
Python 选出列表中特定的元素
|
2月前
|
数据处理 索引 Python
Python列表与元素修改的操作技巧
Python列表提供了丰富的方法和技巧来进行高效的数据操作。熟练运用上述技巧,可以大大提高数据处理的效率和代码的可读性。实践中,根据具体需求灵活选择合适的方法,可以在保证代码效率的同时,也使代码更加简洁明了。
61 2
|
1月前
【LeetCode 01】二分查找总结
【LeetCode 01】二分查找总结
14 0
|
1月前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
70 0
|
2月前
|
数据处理 Python
python遍历文件夹所有文件按什么排序
python遍历文件夹所有文件按什么排序
|
2月前
|
数据处理 Python
Python遍历文件夹所有文件并按指定排序
Python遍历文件夹所有文件并按指定排序
|
6月前
|
存储 索引 Python
leetcode-350:两个数组的交集 II(python中Counter的用法,海象运算符:=)
leetcode-350:两个数组的交集 II(python中Counter的用法,海象运算符:=)
54 0