【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】
上期笔记:二叉搜索树的前序、中序、后序遍历方法
题目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)
- 前序:[ 3, 9, 20, 15, 7] 中序:[ 9, 3, 15, 20, 7]
- 代码:
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, 3 ]
(红色表示当前节点,蓝色表示左子树,绿色表示右子树)
- 代码:
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, 2, 6, 7, 3, 1 ]
(红色表示当前节点,蓝色表示左子树,绿色表示右子树)
- 注意只有一个节点的情况:如 [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)