1. 题目
https://leetcode.cn/problems/validate-binary-search-tree/
考察点
这道题的考察点是:
- 对二叉搜索树的定义和性质的理解和掌握。
- 对递归和迭代的思想和实现的熟练度。
- 对中序遍历的原理和应用的掌握。
- 对边界值和特殊情况的处理能力。
2. 解法
背景:什么是二叉搜索树
二叉搜索树是一种特殊的二叉树,它的每个结点都有一个关键字,而且满足以下性质:
- 左子树上所有结点的关键字都小于根结点的关键字。
- 右子树上所有结点的关键字都大于根结点的关键字。
- 左右子树也都是二叉搜索树。
- 没有两个结点的关键字相同。
二叉搜索树可以高效地进行查找、插入和删除操作,因为它可以利用关键字的顺序信息
二种解法
- 递归
- 迭代
解法一:递归
思路
算法的思路是这样的:
- 定义一个递归函数,接受一个节点和一个上下界作为参数,表示要检查的子树和合法的范围。
- 如果节点为空,返回true,表示空节点是有效的。
- 如果节点的值不在上下界内,返回false,表示节点不满足二叉搜索树的条件。
- 递归地检查节点的左子树和右子树,左子树的上界是节点的值,右子树的下界是节点的值,如果有任何一个返回false,就返回false,否则返回true。
- 在主函数中,调用递归函数,传入根节点和最小值和最大值作为参数。
具体实现
class Solution { public boolean isValidBST(TreeNode root) { return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE); } private boolean isValidBST(TreeNode node, long lower, long upper) { if (node == null) return true; // 空节点是有效的 if (node.val <= lower || node.val >= upper) return false; // 节点值不在范围内 return isValidBST(node.left, lower, node.val) && isValidBST(node.right, node.val, upper); // 递归检查左右子树 } }
分析
这个算法的优点是简单易懂,逻辑清晰,可以正确地判断二叉搜索树的有效性。它的时间复杂度是O(n),空间复杂度是O(h),其中n是节点的个数,h是树的高度。
这个算法的缺点是需要额外的空间来存储上下界,而且对于边界值可能会有溢出的风险,比如如果节点的值是整型的最大值或最小值。另外,它没有利用二叉搜索树的中序遍历是有序的这一性质,可能会有更优化的方法。
解法二:迭代
思路
具体实现
class Solution { public boolean isValidBST(TreeNode root) { // 定义一个栈,用来存储节点 Stack<TreeNode> stack = new Stack<>(); // 定义一个变量,记录前一个节点的值 long prev = Long.MIN_VALUE; // 定义一个指针,指向当前节点 TreeNode curr = root; // 当栈不为空或者指针不为空时,循环 while (!stack.isEmpty() || curr != null) { // 如果指针不为空,将其压入栈中,然后向左移动 while (curr != null) { stack.push(curr); curr = curr.left; } // 如果指针为空,弹出栈顶元素,作为当前节点 curr = stack.pop(); // 检查当前节点是否大于前一个节点 if (curr.val <= prev) return false; // 更新前一个节点的值 prev = curr.val; // 将指针指向当前节点的右子节点 curr = curr.right; } // 如果循环结束,没有返回false,说明是有效的二叉搜索树,返回true return true; } }