Python算法题集_搜索插入位置
- 题51:搜索插入位置
- [1. 示例说明](#1. 示例说明)
- [2. 题目解析](#2. 题目解析)
-
- [- 题意分解](#- 题意分解)
- [- 优化思路](#- 优化思路)
- [- 测量工具](#- 测量工具)
- [3. 代码展开](#3. 代码展开)
-
- 1) 标准求解【二分法查找】 标准求解【二分法查找】)
- 2) 改进版一【二分法查找+终止条件判断】 改进版一【二分法查找+终止条件判断】)
- 3) 改进版二【第三方模块】 改进版二【第三方模块】)
- [4. 最优算法](#4. 最优算法)
- [5. 相关资源](#5. 相关资源)
本文为Python算法题集之一的代码示例
题51:搜索插入位置
1. 示例说明
-
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为
O(log n)
的算法。示例 1:
输入: nums = [1,3,5,6], target = 5 输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2 输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7 输出: 4
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums
为 无重复元素 的 升序 排列数组-104 <= target <= 104
2. 题目解析
- 题意分解
- 本题是在已排序的整数数组中查找目标数字的插入位置
- 最快方式就是二分法
- 优化思路
-
通常优化:减少循环层次
-
通常优化:增加分支,减少计算集
-
通常优化:采用内置算法来提升计算速度
-
分析题目特点,分析最优解
-
二分法中可以采用终止条件判断
-
可以考虑使用排序列表操作模块
bisect
-
- 测量工具
- 本地化测试说明:LeetCode网站测试运行时数据波动很大【可把页面视为功能测试】,因此需要本地化测试解决数据波动问题
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块- 本题本地化超时测试用例自己生成,详见章节【最优算法】,代码文件包含在【相关资源】中
3. 代码展开
1) 标准求解【二分法查找】
通过二分法查找目标数值应插入位置
页面功能测试,性能一般,超过79%
python
import CheckFuncPerf as cfp
class Solution:
def searchInsert_base(self, nums, target):
ileft, iright = 0, len(nums)
while ileft < iright:
imid = (ileft + iright) // 2
if nums[imid] >= target:
iright = imid
else:
ileft = imid + 1
return ileft
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchInsert_base, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
# 运行结果
函数 searchInsert_base 的运行时间为 1.00 ms;内存使用量为 4.00 KB 执行结果 = 99999985
2) 改进版一【二分法查找+终止条件判断】
通过二分法查找目标数值应插入位置,检测中进行终止条件判断
页面功能测试,马马虎虎,超过35%
python
import CheckFuncPerf as cfp
class Solution:
def searchInsert_ext1(self, nums, target):
ileft, iright = 0, len(nums) - 1
while ileft <= iright:
imid = (iright - ileft) // 2 + ileft
if target == nums[imid]:
return imid
if target < nums[imid]:
iright = imid - 1
else:
ileft = imid + 1
return ileft
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchInsert_ext1, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
# 运行结果
函数 searchInsert_ext1 的运行时间为 0.00 ms;内存使用量为 0.00 KB 执行结果 = 99999985
3) 改进版二【第三方模块】
使用排序列表操作模块bisect
来查找插入位置
页面功能测试,马马虎虎,超过29%
python
import CheckFuncPerf as cfp
class Solution:
def searchInsert_ext2(self, nums, target):
from bisect import bisect_left
return bisect_left(nums, target)
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchInsert_ext2, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
# 运行结果
函数 searchInsert_ext2 的运行时间为 1.00 ms;内存使用量为 16.00 KB 执行结果 = 99999985
4. 最优算法
根据本地日志分析,最优算法为第2种方式【二分法查找+终止条件判断】 searchInsert_ext1
本题测试数据,似乎能推出以下结论:
- 在排序数组上使用二分法查询,性能非常夸张,简直是瞬间定位【1亿的数组,1毫秒定位】
- 既然性能不是问题,那么可维护性越好越有利,推荐使用第三种解法
python
ilen = 100000000
isize = ilen // 2
itarget = 0
while isize > 4:
itarget += isize
isize = isize // 2
nums = [x for x in range(ilen)]
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.searchInsert_base, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(aSolution.searchInsert_ext1, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(aSolution.searchInsert_ext2, nums, itarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
# 算法本地速度实测比较
函数 searchInsert_base 的运行时间为 1.00 ms;内存使用量为 4.00 KB 执行结果 = 99999985
函数 searchInsert_ext1 的运行时间为 0.00 ms;内存使用量为 0.00 KB 执行结果 = 99999985
函数 searchInsert_ext2 的运行时间为 1.00 ms;内存使用量为 16.00 KB 执行结果 = 99999985
5. 相关资源
本文代码已上传到CSDN,地址:Python算法题源代码_LeetCode(力扣)_搜索插入位置
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~