Bootstrap

二叉搜索树刷题笔记:第K小的元素,最小绝对差,从前序与中序遍历序列构造二叉树、中序与后序、前序与后序

【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】

上期笔记:二叉搜索树的前序、中序、后序遍历方法

二叉搜索树学习笔记:验证二叉搜索树的三种解法-CSDN博客

题目1: 二叉搜索树中第 K 小的元素【HOT100】

230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

  • 思路:搜索二叉树的中序遍历可以得到递增排序,按遍历顺序取第 K  个
  • 遍历顺序:左子树 → 当前节点 → 右子树
    【二叉搜索树的中序遍历得到的结果是有序(递增)的:1→ 2 → 3 → 4 → 5 → 6 

     
  • 代码:
    class Solution:
        def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
            count = 0  # 按照遍历顺序计数
            result = None  # 记录第k个的结果
    
            def dfs(root):
                if not root: return 
                    
                dfs(root.left)  # 先遍历左子树
                # 处理当前节点
                nonlocal count, result
                count += 1   # 计数
                if count == k:   # 如果是第k个,就记录result
                    result = root.val
    
                dfs(root.right)  # 后遍历右子树
    
            dfs(root)
            return result

题目2:二叉搜索树的最小绝对差 

 530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

  • 思路:和题目1类似,通过中序遍历转化为递增数列,记录每个绝对差取最小
  • 变化(需要记录的值):前一个节点pre的值
    【 绝对差 = pre.val - root.val,这里root表示当前遍历到的节点】
  • 代码:
    class Solution:
        def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
            result = inf # 记录结果
            pre = -inf  # 记录前一个节点值(第一个节点不能算结果,所以第一个节点的绝对差会记为inf)
            def dfs(root):
                if not root: return 
                    
                dfs(root.left)      
                # 【变化部分】
                val = root.val
                nonlocal result, pre
                result = min(result, val-pre) # 更新结果
                pre = val  # 更新前一个节点值
    
                dfs(root.right)  
            
            dfs(root)
            return result

题目3: 从前序与中序遍历序列构造二叉树

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

  • 思路:在前序和中序中找到 “当前节点、左子树、右子树”
  • 拆解:
    • 前序:[ 3, 9, 20, 15, 7]            中序:[ 9, 3, 15, 20, 7]
      红色表示当前节点,蓝色表示左子树,绿色表示右子树)
    • 前序和中序的作用:
      • 前序 — 找到当前节点(第一个
      • 中序 — 划分左子树和右子树(当前节点左边为左子树,右边为右子树)
    • 步骤:
      • 在前序中找到当前节点值(第一个)【 preorder[0] 】
      • 在中序中定位当前节点【 inorder.index(preorder[0]) 】
        (中序中当前节点的index值 = 左子树的节点数量 left_size)
      • 构建左子树:前序为 preorder[1: 1 + left_size],中序为 inorder[:left_size]
      • 构建右子树:前序为 preorder[1+left_size:],中序为 inorder[1+left_size:]
      • 当前的树 TreeNode(preorder[0], left, right)
  • 代码:
    class Solution:
        def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
            if not preorder:
                return None
            left_size = inorder.index(preorder[0])
            left = self.buildTree(preorder[1: 1+left_size], inorder[:left_size])
            right = self.buildTree(preorder[1+left_size:], inorder[1+left_size:])
            return TreeNode(preorder[0], left, right)

题目4: 从中序与后序遍历序列构造二叉树

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

  • 思路:和上题一样
  • 变化:在前序中找到当前节点(第一个)  → 在后序中找到当前节点(最后一个)
  •  中序:[ 9, 3, 15, 20, 7]           后序:[ 9, 15, 7, 20, ]     
    红色表示当前节点,蓝色表示左子树,绿色表示右子树)
  • 代码:
    class Solution:
        def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
            if not postorder:
                return None
            left_len = inorder.index(postorder[-1])
            left = self.buildTree(inorder[:left_len], postorder[:left_len])
            right = self.buildTree(inorder[left_len+1:], postorder[left_len:-1])
            return TreeNode(postorder[-1], left, right)

题目5:根据前序和后序遍历构造二叉树

889. 根据前序和后序遍历构造二叉树 - 力扣(LeetCode)

  • 变化:前序和后序的作用):
    • 前序 — 找到当前节点第一个)、找到左节点第二个
    • 后序 — 划分左子树和右子树(左节点及左边都为左子树,右边至倒数第二个为右子树)
  •  前序:[ 1, 2, 4, 5, 3, 6, 7]            后序:[ 4, 5, 26, 7, 3, ]   
    红色表示当前节点,蓝色表示左子树,绿色表示右子树)
  • 注意只有一个节点的情况:如 [1],要单独处理
  • 代码:
    class Solution:
        def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
            if not preorder:
                return None
            if len(preorder) == 1:  # 只有一个节点
                return TreeNode(preorder[0])
            left_len = postorder.index(preorder[1]) + 1
            left = self.constructFromPrePost(preorder[1:1+left_len], postorder[:left_len])
            right = self.constructFromPrePost(preorder[1+left_len:], postorder[left_len:-1])
            return TreeNode(preorder[0], left, right)

;