秋招算法备战第20天 | 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

654. 最大二叉树 - 力扣(LeetCode)

一开始的代码版本如下所示

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 0:
            return None
        max_num = max(nums)
        max_index = nums.index(max_num)
        root = TreeNode(val=max_num)
        root.left = self.constructMaximumBinaryTree(nums[:max_num])
        root.right = self.constructMaximumBinaryTree(nums[max_num:])
        return root

这里犯了个低级错误,递归调用的时候参数应该分别是nums[:max_index]以及nums[max_index+1:],需要把当前这个元素给略掉,修正后AC的代码如下

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 0:
            return None
        max_num = max(nums)
        max_index = nums.index(max_num)
        root = TreeNode(val=max_num)
        root.left = self.constructMaximumBinaryTree(nums[:max_index])
        root.right = self.constructMaximumBinaryTree(nums[max_index+1:])
        return root

617. 合并二叉树 - 力扣(LeetCode)

递归方法构造,使用递归三部曲依次分析

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if root1 == None and root2 == None:
            return None
        
        val1 = 0 if root1 == None else root1.val
        val2 = 0 if root2 == None else root2.val
        cur = TreeNode(val1+val2)

        root1_left, root1_right = (None, None) if root1 == None else (root1.left, root1.right)
        root2_left, root2_right = (None, None) if root2 == None else (root2.left, root2.right)

        cur.left = self.mergeTrees(root1_left, root2_left)
        cur.right = self.mergeTrees(root1_right, root2_right)
        
        return cur

看了下参考代码,发现有两点可以优化:

  1. 如果有一个为空可以直接剪枝
  2. 可以不用新建结点而是直接修改root1结点
python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
        # 递归终止条件: 
        #  但凡有一个节点为空, 就立刻返回另外一个. 如果另外一个也为None就直接返回None. 
        if not root1: 
            return root2
        if not root2: 
            return root1
        # 上面的递归终止条件保证了代码执行到这里root1, root2都非空. 
        root1.val += root2.val # 中
        root1.left = self.mergeTrees(root1.left, root2.left) #左
        root1.right = self.mergeTrees(root1.right, root2.right) # 右
        
        return root1 # ⚠️ 注意: 本题我们重复使用了题目给出的节点而不是创建新节点. 节省时间, 空间. 

700. 二叉搜索树中的搜索 - 力扣(LeetCode)

根据二叉搜索树性质可得

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if root == None:
            return None
        if root.val == val:
            return root
        elif root.val > val:
            return self.searchBST(root.left, val)
        else:
            return self.searchBST(root.right, val)

98. 验证二叉搜索树 - 力扣(LeetCode)

利用二叉树特性,进行中序遍历,在遍历过程中判断结点的值是否是递增的,并且加入了一些剪枝降低某些情况的时间复杂度

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        last_num = float('-inf')

        def traversal(cur):
            nonlocal last_num
            if cur == None:
                return True

            left_res = traversal(cur.left)
            if not left_res:
                return False
            
            if last_num >= cur.val:
                return False
            last_num = cur.val

            right_res = traversal(cur.right)
            if not right_res:
                return False
            return True

        return traversal(root) 

GPT4对于上面代码给出了一点建议,即在判断None的时候使用is而不是==

is None== None在大多数情况下都能得到相同的结果,但是它们的检查机制是不同的。

  • is None 是检查对象的身份,也就是说它检查两个引用是否指向内存中的同一个对象。在Python中,None是一个单例对象,也就是说在内存中只有一个None。因此,is None就是检查一个对象是否就是这个特定的None对象。

  • == None 是检查对象的值,也就是说它检查两个对象的值是否相等。对于None来说,这通常和is None得到相同的结果。但是,如果一个对象重写了__eq__()方法来改变==的行为,那么== None可能会得到不同的结果。

因此,如果你想要检查一个对象是否为None,那么应该使用is None,因为这样可以保证无论__eq__()如何被重写,你都可以得到正确的结果。

这就是is None== None的主要区别。在Python社区,通常推荐使用is Noneis not None来检查一个对象是否为None

总结

  1. 递归中记得考虑剪枝来降低某些情况下的时间复杂度
  2. 在python中,判断是否为None推荐用is和is not
相关推荐
是店小二呀7 分钟前
【动态规划 | 子序列问题】子序列问题的最优解:动态规划方法详解
算法·动态规划·代理模式
啊我不会诶42 分钟前
BD202402跑步 线性求逆元 素数筛 数学
学习·算法·补题
遇见尚硅谷1 小时前
挑战指针题
c语言·数据结构·算法
是阿建吖!1 小时前
【优选算法】分治--归并排序
数据结构·算法·排序算法
CoovallyAIHub1 小时前
轻量?智能?协同?你选的标注工具,到底有没有帮你提效?
深度学习·算法·计算机视觉
roman_日积跬步-终至千里1 小时前
【机器学习】(算法优化一)集成学习之:装袋算法(Bagging):装袋决策树、随机森林、极端随机树
算法·机器学习·集成学习
ikkkkkkkl2 小时前
LeetCode:209.长度最小的子数组&&3.无重复字符的最长子串
数据结构·c++·算法·leetcode
记录Java学习的三木2 小时前
每日一leetcode:移动零
算法
桦02 小时前
[找出字符串中第一个匹配项的下标]
算法·leetcode
恣艺2 小时前
LeetCode 140:单词拆分 II
算法·leetcode·职场和发展