代码随想录算法训练营day20 | 654.最大二叉树,617.合并二叉树,700.二叉搜索树中的搜索,98.验证二叉搜索树

654.最大二叉树(medium)

  • 这道题解题思路与#106和#105构造二叉树一样,甚至更加直观,因为题目明确指出利用prefix数组来创建左子树,利用suffix数组来创建右子树。

  • 递归法

# 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]: #step1
        #step2
        if not nums:
            return None
        
        rootValue = max(nums)
        root = TreeNode(rootValue)
        if len(nums) == 1:
            return root
        
        #step3
        index = nums.index(rootValue)
        prefix = nums[:index]
        suffix = nums[index+1:]
        
        root.left = self.constructMaximumBinaryTree(prefix)
        root.right = self.constructMaximumBinaryTree(suffix)
        
        return root
        

617.合并二叉树

  • 同时操作两个二叉树也就是将两个二叉树作为参数传入

  • 题解:

# 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]:#step1
        #step2
        if root1 is None:
            return root2
        if root2 is None:
            return root1
        
        #step3
        root = TreeNode()
        if root1 and root2:
            root.val = root1.val + root2.val
            
        root.left = self.mergeTrees(root1.left, root2.left)
        root.right = self.mergeTrees(root1.right, root2.right)
        
        return root

700.二叉搜索树中的搜索

  • 注意二叉搜索树的特性,何时终止搜索

错误点:

  • 需要将递归的返回值赋予一个变量,最后返回该变量。
  • trick:只要调用递归函数时就需要注意该递归函数是否有返回值。
  • 递归法:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def searchBST(self, root, val): #step1
        """
        :type root: TreeNode
        :type val: int
        :rtype: TreeNode
        """
        #step2
        if root is None:
            return None
        if root.val == val:
            return root
        
        #step3
        if root.val > val:
            res = self.searchBST(root.left, val)
        if root.val < val:
            res = self.searchBST(root.right, val)
            
        return res
        
  • 迭代法:

# 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]:
        while root:
            if root.val > val:
                root = root.left
            elif root.val < val:
                root = root.right
            else:
                return root

98.验证二叉搜索树

  • 思路:利用中序遍历,返回一个排好序(ascending)的数组,依此来进行判断

  • 递归法:

# 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:
        res = []
        '''采用中序遍历,因为返回的结果是一个排好序的数组,可依次来进行判断'''
        def traversal(root): #step1: parameter and return type
            #step2: base condition
            if root is None:
                return res

            #step3: logic
            if root.left:
                traversal(root.left)
                
            res.append(root.val)
            
            if root.right:
                traversal(root.right)

        traversal(root)
        return res == sorted(res) and len(res) == len(set(res))
            
  • Carl视频思路:中序遍历,定义一个值并不断更新来记录上一个节点的值。由于中序遍历+二叉搜索树的特性决定了新遍历到的节点的值一定要大于之前的值,否则不是一个二叉搜索树。

# 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:
        maxV = -float('inf')
        
        def helper(root):#step1
            nonlocal maxV
            #step2
            if root is None:
                return True
            #step3
            #左
            left = helper(root.left)
            #中
            if root.val > maxV:
                maxV = root.val
            else:
                return False
            #右
            right = helper(root.right)

            return left and right
        
        return helper(root)

知识点:

  1. nonlocal: The nonlocal keyword won’t work on local or global variables and therefore must be used to reference variables in another scope except the global and local one. The nonlocal keyword is used in nested functions to reference a variable in the parent function. 

  2. global

    A global keyword is a keyword that allows a user to modify a variable outside the current scope. It is used to create global variables from a non-global scope, i.e. inside a function. Global keyword is used inside a function only when we want to do assignments or when we want to change a variable. Global is not needed for printing and accessing.

    Rules of global keyword:

    1. If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global.
    2. Variables that are only referenced inside a function are implicitly global.
    3. We use a global keyword to use a global variable inside a function.
    4. There is no need to use global keywords outside a function.

References:

  • 避免nonlocal关键词写法:

# 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:
        self.cur_max = -float("inf") #通过 self. 来定义,类似全局变量,因此可以在辅助函数里调用
        return self.__isValidBST(root)
    
    def __isValidBST(self, root: TreeNode) -> bool: #step1
            #step2
            if not root: 
                return True
            #step3
            #左
            is_left_valid = self.__isValidBST(root.left)
            #中
            if self.cur_max < root.val: 
                self.cur_max = root.val
            else: 
                return False
            #右
            is_right_valid = self.__isValidBST(root.right)
            
            return is_left_valid and is_right_valid

python知识点:

  • 上面避免nonlocal关键词的正确(正式)写法应该是将所有全局变量都在__init__函数中定义。(参考day21 501.二叉搜索树中的众数下总结)
  • 双指针递归法:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        
        self.pre = None
        return self.helper(root)
        
        
    def helper(self, cur):#step1
        #step2
        if cur is None:
            return True
        #step3
        #左
        is_left_valid = self.helper(cur.left)
        #中
        if self.pre and self.pre.val >= cur.val:
            return False
        self.pre = cur
        #右
        is_right_valid = self.helper(cur.right)
            
        return is_left_valid and is_right_valid

总结:

了解了更多关于二叉树的操作,也加深了对递归写法的理解。主要是不重要着急写,一定要先分析好,比如采用何种遍历方式,二叉树的关键特性等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值