玩转二分法(python版)——leetcode二分法题总结【简单易懂】

在正式写总结前,我想说一下我踩过的那些坑,当时脑袋都要晕掉了,于是花了两天时间搞明白了二分法,写了这篇总结。

我踩过的那些坑:之前采用while left <= right,经常遇到死循环。而且代码分支很多,经常考虑不到特殊情况,最后把自己绕晕了到底有多少种特殊情况。两天得此总结。

二分法【三步走】方法

1、先确定边界。一般情况下left=0,right=len(nums)-1是数组的索引值,但是如果可能遇到答案是含有最大索引值+1的情况(参考leetcode35题),那么right=len(nums)。

2、while循环部分:然后确定选择左中位数和右中位数(最重要)。一般情况下,看中位数所在的值是不是通过left和right的移动能完全排除,如果都可以完全排除,那选择左中位数和右中位数都可以(参考leetcode704),如果不能完全排除,看左中位数移动left能不能完全排除(看有中位数移动right能不能完全排除)。而且如果选择左中位数,mid = (left + right)/2 left = mid + 1 right = mid;选择右中位数,mid=(left+right+1)/2 right = mid - 1 left = mid。很多情况下,使用左中位数会出现死循环,此时mid=right,解决的方法就是采用右中位数。

实践经验:一般情况下,【1】先选择左中位数,看nums[mid]是不是在第一个if逻辑中完全排除即可以按照left=mid+1,【2】再用两个数的数组验证一下会不会造成死循环,如果不会,那这样ok的。如果进入死循环,那选择右中位数,同时mid = (left + right + 1) // 2 并且 right = mid - 1

3、返回left值前,先看看值在不在数组里,如果一定在,那就不用判断直接返回left,如果不一定在数组里,那么需要判断一下这个值是不是要找的那个,如果不是返回-1。

基本思想

【参考博客,这位大佬说的很清楚可以结合这篇博文和我这篇一起看https://leetcode-cn.com/problems/two-sum/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/

(1)首先把循环可以进行的条件写成 while(left < right),在退出循环的时候,一定有 left == right 成立,此时返回 left 或者 right 都可以

  • 或许你会问:退出循环的时候还有一个数没有看啊(退出循环之前索引 left 或 索引 right 上的值)? 没有关系,我们就等到退出循环以后来看,甚至经过分析,有时都不用看,就能确定它是目标数值。更深层次的思想是“夹逼法”或者称为“排除法”。

  • 最重点的要注意:在确定核心逻辑时,应该这样想,看mid是否完全排除,如果是 left = mid+1,照这个思路就可,放心,不会错。(此时可能你看不懂,但是看完全文就懂了)

(2)“神奇的”二分查找法模板的基本思想(特别重要)

  • “排除法”即:在每一轮循环中排除一半以上的元素,于是在对数级别的时间复杂度内,就可以把区间“夹逼” 只剩下 1 个数,而这个数是不是我们要找的数,单独做一次判断就可以了。

  • “夹逼法”或者“排除法”是二分查找算法的基本思想,“二分”是手段,在目标元素不确定的情况下,“二分” 也是“最大熵原理”告诉我们的选择。

接下来,让我先甩出来二分法模板!

二分法模板:

def search(nums, target):
    if nums is None or len(nums) == 0:
        return -1
    left = 0
    right = len(num)-1 #【第一步需要判断的】
    while left < right:
        mid = (left + right) // 2 #【第二步需要判断的】
        #mid = (left + right +1) // 2
        if nums[mid] > target:#条件,需要逻辑判断,此时要避免死循环
            left = mid + 1
        else:
            right = mid
    return left #【第三步要思考的】看是否要判断这个if nums[left] == target
    

基本模板就是这样,接下来就是实践,积累经验。

目前做过的题有:704、69、34、35、153、154、33、81、4

推荐按照这个顺序做题

下面有这些题的答案(我自己写的,还有很多不足之处,欢迎讨论)

leetcode[704二分查找]——常规法

题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

下面代码是用左中位法:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1 #第一步:判断返回值是不是能超出边界,此题不会超出边界
        while left < right:
            mid = (left + right) // 2 #第二步:判断选择左中位法还是右中位法,对于有序二
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值