🌳 理解与掌控二叉搜索树:高阶操作全解析(LeetCode 98 / 230 / 101)
这一篇聚焦于二叉搜索树(BST)相关的高阶题型,包括验证、查询、以及树结构的对称性判断。比起基本的遍历与构造,这些题目更强调我们对 BST 性质的深刻理解与灵活运用。
✨ 一、验证二叉搜索树(LeetCode 98)
🧩 题目描述
判断一棵二叉树是否为一棵有效的二叉搜索树(BST)。BST 的定义是:
- 对于每个节点:
- 左子树所有节点的值 < 当前节点的值;
- 右子树所有节点的值 > 当前节点的值;
- 左右子树也必须是 BST。
💡 解题思路一:中序遍历 + 判断递增
BST 的中序遍历结果应该是严格递增的,因此我们只需中序遍历并检查元素顺序是否符合要求。
func isValidBST(root *TreeNode) bool {
var prev *TreeNode
var dfs func(*TreeNode) bool
dfs = func(node *TreeNode) bool {
if node == nil {
return true
}
if !dfs(node.Left) {
return false
}
if prev != nil && node.Val <= prev.Val {
return false
}
prev = node
return dfs(node.Right)
}
return dfs(root)
}
🔍 解题要点
- 注意不能单纯比较当前节点与左右子节点的值;
- 应使用一个
prev指针记录中序遍历过程中的前一个节点值。
✨ 二、二叉搜索树中第 K 小的元素(LeetCode 230)
🧩 题目描述
给定一棵 BST,返回其中第 k 小的元素。
💡 解题思路:中序遍历 + 计数
中序遍历 BST 可获得递增序列,因此只需中序遍历到第 k 个节点。
func kthSmallest(root *TreeNode, k int) int {
count := 0
var result int
var inorder func(*TreeNode)
inorder = func(node *TreeNode) {
if node == nil {
return
}
inorder(node.Left)
count++
if count == k {
result = node.Val
return
}
inorder(node.Right)
}
inorder(root)
return result
}
🔍 解题要点
- 可提前剪枝优化,达到第 k 个元素即可终止;
- 如果是频繁查询,建议使用二叉搜索树带节点计数的增强结构。
✨ 三、对称二叉树(LeetCode 101)
🧩 题目描述
判断一棵二叉树是否是镜像对称的。
💡 解题思路:递归判断左右子树是否互为镜像
func isSymmetric(root *TreeNode) bool {
var check func(p, q *TreeNode) bool
check = func(p, q *TreeNode) bool {
if p == nil && q == nil {
return true
}
if p == nil || q == nil || p.Val != q.Val {
return false
}
return check(p.Left, q.Right) && check(p.Right, q.Left)
}
return check(root.Left, root.Right)
}
🔍 解题要点
- 核心在于左右节点相互对称的判断;
- 也可以使用队列迭代实现(层序遍历的对称判断)。
🧠 总结回顾
| 题目编号 | 名称 | 解题关键点 |
|---|---|---|
| 98 | 验证 BST | 中序遍历是否递增,递归边界与比较逻辑 |
| 230 | K 小元素 | 中序遍历第 k 个,考虑剪枝或平衡树优化 |
| 101 | 对称二叉树 | 递归判断左右节点是否对称镜像 |
这些题目共同体现出对 BST 和树结构对称性的深入理解与处理技巧。
📌 后记建议
- 熟悉 BST 的性质是高效解题的关键;
- 中序遍历是解决很多 BST 问题的核心切入点;
- 「镜像对称」虽然不一定出现在 BST 中,但在树结构的理解中非常重要。
如果你喜欢这类主题划分清晰、解法详尽的算法笔记,欢迎持续关注下一篇关于「二叉树构造」的内容!