来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/validate-binary-search-tree
题意:
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:root = [2,1,3]
输出:true
示例 2:
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。
提示:
树中节点数目范围在[1, 104] 内
-231 <= Node.val <= 231 - 1
参考文章
思路:
做这道题之前,首先要理解二叉搜索树的概念与特点。
其次,做这道题的时候容易陷入一个陷阱,就是只单纯地将中间节点与左节点和右节点进行比较,直接返回结果。我第一次写这道题时候的代码是:
class Solution {
public boolean isValidBST(TreeNode root) {
boolean ans = true;
if (root.left != null) ans = ans && root.val > root.left.val && isValidBST(root.left);
if (root.right != null) ans = ans && root.val < root.right.val && isValidBST(root.right);
return ans;
}
}
直接就WA了,解答错误的测试用例是:[5,4,6,null,null,3,7],预期结果是false,而代码返回的结果是true。这个测试用例所形成的树是:
在这个测试用例中,每个节点都满足左节点小于中间节点、右节点大于中间节点,所以代码返回的结果是true,但是实际上这个测试用例并不满足二叉搜索树的定义,节点值为3的节点是不应该出现在这个位置的
递归法:
这道题的第一个做法是,利用二叉搜索树的特点,我们直接使用中序遍历得到二叉搜索树节点的有序序列,判断这个有序序列是否是真的有序即可
以上做法的Java代码:
class Solution {
private List<Integer> list;
private void travel(TreeNode node) {
if (node == null)
return;
travel(node.left);
list.add(node.val);
travel(node.right);
}
public boolean isValidBST(TreeNode root) {
list = new ArrayList<>();
travel(root);
for (int i = 0; i < list.size() - 1; i++) {
if (list.get(i) >= list.get(i + 1))
return false;
}
return true;
}
}
但其实我们也可以不将遍历结果转变为数组进行判断,可以在递归获取遍历序列的过程中直接进行判断是否有序。
以上做法的Java代码:
class Solution {
TreeNode rnNode;//记录当前遍历到的节点
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
boolean left = isValidBST(root.left);
if (rnNode != null && rnNode.val >= root.val) return false;
rnNode = root;
boolean right = isValidBST(root.right);
return left && right;
}
}
迭代法:
迭代法其实就是不用递归方法来遍历,而是改用一个栈来实现中序遍历,即迭代的方式,思路与上面的递归法是一样的,都是在中序遍历的过程中直接进行判断是否有序
以上做法的Java代码:
class Solution {
public boolean isValidBST(TreeNode root) {
TreeNode rnNode = null;// 记录当前中序遍历序列的最后一个节点
TreeNode curNode = root;
Deque<TreeNode> deque = new LinkedList<>();
while (curNode != null || !deque.isEmpty()) {
if (curNode != null) {
deque.push(curNode);
curNode = curNode.left;
} else {
curNode = deque.poll();
if (rnNode != null && curNode.val <= rnNode.val)
return false;
rnNode = curNode;
curNode = curNode.right;
}
}
return true;
}
}