秋招算法备战第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以及numsmax_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
相关推荐
Reart4 分钟前
Leetcode 188.买卖股票的最佳时机4(718)
后端·算法
2601_950760796 分钟前
BCMA:急性髓系白血病免疫治疗的新型可行靶点
人工智能·算法·蛋白
Reart19 分钟前
Leetcode 123.买卖股票的最佳时期3(内有随心谈,718)
后端·算法
可编程芯片开发1 小时前
基于RMDCFT算法的天基雷达空间机动目标检测方法MATLAB仿真,对比FRFT和DFT算法
算法
noipp1 小时前
推荐题目:洛谷 B2099 矩阵交换行
线性代数·算法·矩阵
五条凪3 小时前
简单理解 BM25 与 TF-IDF
人工智能·算法·搜索引擎·全文检索·tf-idf
行者全栈架构师3 小时前
【码动四季】Spring Boot 可观测性体系:Micrometer + OpenTelemetry + Grafana 全链路搭建
java·算法·架构
TCW11213 小时前
AI底层系列:用C++实现线性代数的公式推导与算法设计-8.线性变化(3)
c++·人工智能·算法
皓月斯语4 小时前
B3849 [GESP样题 三级] 进制转换 题解
c++·算法·题解
中微极客4 小时前
剪枝与量化:让YOLO在边缘设备上高效部署
算法·yolo·剪枝