进阶计划_算法思维_挑战100天_DAY12

  学习目标:

  • 掌握几种基本的算法结构,实现算法问题解决的基本思维

学习内容:

题目:搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 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中是否有该元素,有则输出该元素的下标即可。没有那就加入该列表,并用sort进行排序,最后返回该元素的下标即可。

2、看到一个算友整理的关于二分法的思维导图不错,这里可以分享给大家:

后续可以参考模版进行类题的输出:

1.先确定查找区间的左右开闭情况
这是写二分查找最根本的问题, 因为根据不同的情况, 下面的操作是完全不同的, 这也是很多朋友感觉二分查找难写的地方, 这里为了方便, 我直接将区间定义为左闭右开[left, right)的形式, 这里根据自己的习惯最好将区间完全固定住, 以后都按照一种模式来写, 如果你习惯左闭右闭也同样固定住, 这样不用每次都纠结.

固定为左闭右开的好处是: 很多函数中对区间的操作都是左闭右开的形式, 这算是语言的特点吧, 比如字符串中截取子串长度, 列表的截取都是左闭右开的形式, 这样就可以和语言特点相对应.

另一个好处就是在返回值的问题上, 下文会提到.

2.数组长度
当区间固定住为左闭右开, 数组长度就固定为[0, len(nums)), 这也是左右端点的初值, 如为左闭右闭, 那长度就是[0, len(nums)-1]了.

3.循环退出条件
这里也要特别注意, 代码为 while left < right 因为区间是右开, 所以不能有=, 否则区间就不存在了, 这样写循环控制的另外一个好处就是在退出循环时, 必然满足 left == right, 这样在最后的返回值就可以任意返回了, 因为它们完全相等, 而不用去纠结该返回哪个端点了.

4.中间值的写法
写法为 mid = left + (right - left)//2 , //2在Python中表示整除, /2在Python中表示正常除, 是有余数的, 这点和其他语言有所不同. 这样写的好处也非常简单, 就是为了防止大数溢出, 因为写成(left + right)//2时, 当数比较大时, left + right是有溢出的风险的, 这种写法就可以避免了.

5.中间值和目标值的比较关系
if nums[mid] < target 这个比较关系涉及到上图中4和5的两种变形, 写成什么样的形式是不固定的, 这里是根据题目要求来写的.

简单来说就是如果是<, 那么当nums[mid]达到是比target小的数中的最大的数的时候, 通过if条件进入, left的值为mid+1后的值必然是大于等于target的值, 这时候可能取到和target相等的位置.

但是当换成≤时, 当nums[mid] == target时, 仍然会进入if条件, left的值为mid+1后的值必然是大于target的值, 这时候就不可能取到和target相等的位置. 就会收敛到第一个大于target的位置.

这点还是有点复杂的, 可以好好多看几遍.

第5条是说数组由递增改为递减, 其实只要将判断条件反过来就可以了, 还是很好理解的.

6.左右区间的变化
区间的变化完全取决于区间的定义, 因为左闭, 所以左区间为left = mid+1, 因为右开, 所以右区间变换为right = mid, 其实真实取的值也就是mid-1

7.最终返回值
最后的返回值上文已经说过了, 随便返回哪个都可以

这个模板算是比较好记忆, 也比较简洁的模板了, 如果你也比较习惯左闭右开的区间, 直接理解记住此模板就可以了, 如果你习惯左闭右闭的区间, 那稍微更改下也就可以了.

学习产出:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值