思维导图整理大厂面试高频数组1: 总结了二分查找的通用模板写法, 彻底解决几个易混淆问题,力扣35:搜索插入位置

举报
孤柒 发表于 2021/12/03 21:24:54 2021/12/03
【摘要】 此专栏文章是对力扣上算法题目各种方法的总结和归纳, 整理出最重要的思路和知识重点并以思维导图形式呈现, 当然也会加上我对导图的详解.目的是为了更方便快捷的记忆和回忆算法重点(不用每次都重复看题解), 毕竟算法不是做了一遍就能完全记住的. 所以本文适合已经知道解题思路和方法, 想进一步加强理解和记忆的朋友, 并不适合第一次接触此题的朋友(可以根据题号先去力扣看看官方题解, 然后再看本文内容)....

此专栏文章是对力扣上算法题目各种方法总结和归纳, 整理出最重要的思路和知识重点并以思维导图形式呈现, 当然也会加上我对导图的详解.

目的是为了更方便快捷的记忆和回忆算法重点(不用每次都重复看题解), 毕竟算法不是做了一遍就能完全记住的. 所以本文适合已经知道解题思路和方法, 想进一步加强理解和记忆的朋友, 并不适合第一次接触此题的朋友(可以根据题号先去力扣看看官方题解, 然后再看本文内容).

关于本专栏所有题目的目录链接, 刷算法题目的顺序/注意点/技巧, 以及思维导图源文件问题请点击此链接.

想进大厂, 刷算法是必不可少的, 欢迎和博主一起打卡刷力扣算法! 博主同步更新了算法视频讲解, 更易于理解, 不想看文章的 欢迎来看!

关注博主获得题解更新的最新消息!!!

文章目录:

题目链接: https://leetcode-cn.com/problems/search-insert-position/

0.导图整理

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.最终返回值

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

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

源码

Python:

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums) #采用左闭右开区间[left,right)
        while left < right: # 右开所以不能有=,区间不存在
            mid = left + (right - left)//2 # 防止溢出, //表示整除
            if nums[mid] < target: # 中点小于目标值,在右侧,可以得到相等位置
                left = mid + 1 # 左闭,所以要+1
            else:
                right = mid # 右开,真正右端点为mid-1
        return left # 此算法结束时保证left = right,返回谁都一样

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。