Python算法题集_在排序数组中查找元素的第一个和最后一个位置

Python算法题集_在排序数组中查找元素的第一个和最后一个位置

  • 题34:在排序数组中查找元素的第一个和最后一个位置
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【二分法+两次左边界】
    • 2) 改进版一【二分法+左右边界】
    • 3) 改进版二【第三方模块】
  • 4. 最优算法
  • 5. 相关资源

本文为Python算法题集之一的代码示例

题34:在排序数组中查找元素的第一个和最后一个位置

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]
    

    示例 3:

    输入:nums = [], target = 0
    输出:[-1,-1]
    

    提示:

    • 0 <= nums.length <= 105
    • -109 <= nums[i] <= 109
    • nums 是一个非递减数组
    • -109 <= target <= 109

2. 题目解析

- 题意分解

  1. 本题是在已排序列表中查找目标数值的左边界和右边界
  2. 最快方式就是二分法

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 可以通过查找左边界的方式执行,查找目标的左边界+查找目标+1的左边界

    2. 可以通过查找左边界、右边界的方式执行

    3. 可以考虑使用排序列表操作模块bisect

- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大【可把页面视为功能测试】,因此需要本地化测试解决数据波动问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题本地化超时测试用例自己生成,详见章节【最优算法】,代码文件包含在【相关资源】中

3. 代码展开

1) 标准求解【二分法+两次左边界】

二分法查询目标值左边界和目标+1左边界

页面功能测试,性能一般,超过78%在这里插入图片描述

import CheckFuncPerf as cfpclass Solution:def searchRange_base(self, nums, target):def searchbig(target: int) -> int:ileft, iright = 0, len(nums)while ileft < iright:imid = ileft + ((iright - ileft) >> 1)if nums[imid] > target:iright = imidelse:ileft = imid + 1return irightistart = searchbig(target - 1)if istart == len(nums) or nums[istart] != target:return [-1, -1]iend = searchbig(target)return [istart, iend - 1]aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchRange_base, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 searchRange_base 的运行时间为 0.00 ms;内存使用量为 4.00 KB 执行结果 = [33333333, 33333334]

2) 改进版一【二分法+左右边界】

二分法查询目标值左边界和右边界

页面功能测试,马马虎虎,超过56%在这里插入图片描述

import CheckFuncPerf as cfpclass Solution:def searchRange_ext1(self, nums, target):result = [-1, -1]def searchbymode(ileft, iright, modeflag):while ileft <= iright:imid = (ileft + iright) // 2if nums[imid] == target:if modeflag:result[0] = imidiright = imid - 1else:result[1] = imidileft = imid + 1elif nums[imid] > target:iright = imid - 1else:ileft = imid + 1searchbymode(0, len(nums) - 1, True)searchbymode(0, len(nums) - 1, False)return resultaSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchRange_ext1, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 searchRange_ext1 的运行时间为 0.00 ms;内存使用量为 4.00 KB 执行结果 = [33333333, 33333334]

3) 改进版二【第三方模块】

使用排序列表操作模块bisect来查找左右边界

页面功能测试,马马虎虎,超过42%在这里插入图片描述

import CheckFuncPerf as cfpclass Solution:def searchRange_ext2(self, nums, target):from bisect import bisect_left, bisect_rightileft = bisect_left(nums, target)if ileft >= len(nums):return [-1, -1]if nums[ileft] != target:return [-1, -1]if ileft == len(nums)-1:return [ileft, ileft]if nums[ileft+1] != target:return [ileft, ileft]iright = bisect_right(nums[ileft+1:], target)return [ileft, ileft+iright]aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchRange_ext2, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 searchRange_ext2 的运行时间为 680.67 ms;内存使用量为 4.00 KB 执行结果 = [33333333, 33333334]

4. 最优算法

根据本地日志分析,最优算法为第1种方式【二分法+两次左边界】、第2种方式【二分法+左右边界】并列

本题测试数据,似乎能推出以下结论:

  1. 二分法查询性能非常夸张,简直是瞬间定位【1亿的数组,1毫秒定位】
  2. 第三方模块的算法估计是进行了切片操作
import random
ilen, istart = 100000000, 0
nums = [0 for x in range(ilen)]
for iIdx in range(ilen):istart += random.randint(0, 3)nums[iIdx] = istart
itarget = nums[ilen // 3]
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchRange_base, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(aSolution.searchRange_ext1, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(aSolution.searchRange_ext2, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 算法本地速度实测比较
函数 searchRange_base 的运行时间为 0.00 ms;内存使用量为 4.00 KB 执行结果 = [33333333, 33333334]
函数 searchRange_ext1 的运行时间为 0.00 ms;内存使用量为 4.00 KB 执行结果 = [33333333, 33333334]
函数 searchRange_ext2 的运行时间为 680.67 ms;内存使用量为 4.00 KB 执行结果 = [33333333, 33333334]

5. 相关资源

本文代码已上传到CSDN,地址:Python算法题源代码_LeetCode(力扣)_在排序数组中查找元素的第一个和最后一个位置

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/527178.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript基础5之作用域、执行上下文的顺序执行、可执行代码、执行上下文栈

JavaScript基础 作用域思考 执行上下文顺序执行可执行代码执行上下文栈案例一案例二case1:case2 作用域 作用域&#xff1a;程序源代码中定义变量的区域。作用域规定了如何查找变量&#xff0c;也就是确定当前执行代码对变量的访问权限。作用域分类&#xff1a;静态作用域&…

Tensorflow2.0+部署(tensorflow/serving)过程备忘记录Windows+Linux

Tensorflow2.0部署&#xff08;tensorflow/serving&#xff09;过程备忘记录 部署思路&#xff1a;采用Tensorflow自带的serving进模型部署&#xff0c;采用容器docker 1.首先安装docker 下载地址&#xff08;下载windows版本&#xff09;&#xff1a;https://desktop.docke…

数学建模【时间序列】

一、时间序列简介 时间序列也称动态序列&#xff0c;是指将某种现象的指标数值按照时间顺序排列而成的数值序列。时间序列分析大致可分成三大部分&#xff0c;分别是描述过去、分析规律和预测未来&#xff0c;本篇将主要介绍时间序列分析中常用的三种模型&#xff1a;季节分解…

一键部署Tesseract-OCR环境C++版本(Windows)

环境&#xff1a;Windows 10 工具&#xff1a;git vcpkg vscode cmake 库&#xff1a;Tesseract 一键部署Tesseract-OCR环境C版本&#xff08;Windows&#xff09; 分享这篇文章的原因很简单&#xff0c;就是为了让后续的朋友少走弯路。自己在搜索相关C版本的tesseract部署时…

Vue class和style绑定:动态美化你的组件

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

wps由于找不到krpt.dll,无法继续执行代码的解决方法

遇到由于找不到krpt.dll,无法继续执行代码的问题时&#xff0c;理解如何修复这个问题变得至关重要。本文会教大家krpt.dll的恢复流程&#xff0c;并介绍该DLL文件的相关属性。我们将一步步指导你如何处理缺失文件的情况&#xff0c;让你能够解决阻碍代码正常运行的障碍&#xf…

round四舍五入在python2与python3版本间区别

round()方法返回数值的小数点四舍五入到n个数字。 语法 以下是round()方法的语法&#xff1a; round( x ,n) 参数 x --这是一个数值&#xff0c;表示需要格式化的数值 n --这也是一个数值,表示小数点后保留多少位 返回值 该方法返回 数值x 的小数点四舍五入到n个数字 …

部署LVS负载均衡集群架构

目录 一、ipvsadm 工具 二、NAT模式下部署LVS负载均衡 1、部署NFS共享存储服务器 1.1 安装NFS软件 1.2 新建共享目录和站点文件 1.3 设置共享策略 2、部署节点服务器1 2.1 安装并启动nginx软件 2.2 挂载共享目录到网页站点目录 2.3 修改网关 3、部署节点服务器2 3.…

ubuntu 20.04 安装 huggingface transformers 环境

1. 安装 cuda 大多数新发布的大语言模型使用了较新的 PyTorch v2.0 版本&#xff0c;Pytorch 官方认为 CUDA 最低版本是 11.8 以及匹配的 GPU 驱动版本。详情见Pytorch官方 如下图&#xff1a; 1.1 下载 cuda cuda 12.1 官方网站&#xff1a; 下载&#xff1a; $wget htt…

17-任务状态

任务状态 实时操作系统的核心就是高效的管理各个任务与任务之间的通信。 任务状态通常分为以下四种&#xff1a; 就绪&#xff08;Ready&#xff09; 运行&#xff08;Running&#xff09; 阻塞&#xff08;Blocked&#xff09; 挂起态(Suspended) 阻塞&#xff1a;如果当…

【JavaScript】JavaScript 变量 ① ( JavaScript 变量概念 | 变量声明 | 变量类型 | 变量初始化 | ES6 简介 )

文章目录 一、JavaScript 变量1、变量概念2、变量声明3、ES6 简介4、变量类型5、变量初始化 二、JavaScript 变量示例1、代码示例2、展示效果 一、JavaScript 变量 1、变量概念 JavaScript 变量 是用于 存储数据 的 容器 , 通过 变量名称 , 可以 获取 / 修改 变量 中的数据 ; …

【SpringCloud】微服务重点解析

微服务重点解析 1. Spring Cloud 组件有哪些&#xff1f; 2. 服务注册和发现是什么意思&#xff1f;Spring Cloud 如何实现服务注册和发现的&#xff1f; 如果写过微服务项目&#xff0c;可以说做过的哪个微服务项目&#xff0c;使用了哪个注册中心&#xff0c;常见的有 eurek…