welcome to my blog
LeetCode Top 100 Liked Questions 98. Validate Binary Search Tree (Java版; Medium)
题目描述
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
Example 1:
2
/ \
1 3
Input: [2,1,3]
Output: true
Example 2:
5
/ \
1 4
/ \
3 6
Input: [5,1,4,null,null,3,6]
Output: false
Explanation: The root node's value is 5 but its right child's value is 4.
class Solution {
public boolean isValidBST(TreeNode root) {
if(root==null){
return true;
}
Stack<TreeNode> s = new Stack<>();
TreeNode cur = root;
long pre = Long.MIN_VALUE;
while(cur!=null || !s.isEmpty()){
if(cur!=null){
s.push(cur);
cur = cur.left;
}else{
cur = s.pop();
if(cur.val <= pre){
return false;
}
pre = cur.val;
cur = cur.right;
}
}
return true;
}
}
第一次做; 可以改成循环版的中续遍历, 其余思想和下面的方法一致
//循环版中序遍历
import java.util.Stack;
class Solution {
public boolean isValidBST(TreeNode root) {
Stack<TreeNode> s = new Stack<>();
TreeNode curr =root;
long pre = Long.MIN_VALUE;
while(!s.isEmpty() || curr!=null){
//一路将左节点压栈
while(curr!=null){
s.push(curr);
curr = curr.left;
}
//直到没有左节点,弹出栈顶元素
curr = s.pop();
if(curr.val <= pre)
return false;
//here, curr.val > pre
//update
pre = curr.val;
//令curr指向curr.right, 看看curr有没有右子树, 有的话就得一路将curr.right的左孩子们压栈
curr = curr.right;
}
return true;
}
}
第一次做; 中续遍历二叉树, 将当前节点的值和便利过程中的前一个值pre比较, 当前节点的值大于pre的话, 就更新pre, 继续遍历; 当前节点的值小于等于pre的话, 返回false; 细节:一开始我用的Integer.MIN_VALUE(等于-2147483648)作为pre的初始值, 结果没有通过, 因为有一个案例的输入是[-2147483648], 这个节点的值等于pre, 所以返回false, 但是应该返回true; 犹豫TreeNode的定义中val是int类型的, 所以我把pre的初始值改成了Long.MIN_VALUE(等于-2^63); 如果节点定义中val是long类型的呢? 其实第一步可以先找到中序遍历中的第一个节点作为pre的初始值, 然后从中续遍历的第二个节点开始与pre比较; 中续遍历可以改成循环版的
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public Long pre = Long.MIN_VALUE; // 有一个输入是[-2147483648],
//递归逻辑: 以当前节点为根的二叉树是否为搜索二叉树
public boolean isValidBST(TreeNode root) {
//input check
if(root==null)
//和面试官商量
return true;
boolean res=false;
//以当前节点的左孩子(新条件新递归)为根的二叉树是否为搜索二叉树
res = isValidBST(root.left);
if(res==false)
return false;
//处理当前输入
//如果当前节点的值小于等于pre, 则返回false
if(root.val <= pre)
return false;
//如果当前节点的值大于pre, 则更新pre
pre = (long)root.val;
//以当前节点的右孩子(新条件新递归)为根的二叉树是否为搜索二叉树
res = isValidBST(root.right);
return res;
}
}
题解, 针对左子树设置上界, 针对右子树设置下界; 最开始我也想着用类似的方法做, 但是没想到怎么设置界限, 也没想到需要设置上下界; 更没想到需要对左子树设置上界, 对右子树设置下界; 看图就知道为什么需要上下界了
下图不是搜索二叉树, 因为右子树有一个节点的val小于根节点的val, 事实上, 右子树所有节点的val都应该大于根节点的val
原图链接
class Solution {
public boolean helper(TreeNode node, Integer lower, Integer upper) {
if (node == null) return true;
int val = node.val;
if (lower != null && val <= lower) return false;
if (upper != null && val >= upper) return false;
if (! helper(node.right, val, upper)) return false;
if (! helper(node.left, lower, val)) return false;
return true;
}
public boolean isValidBST(TreeNode root) {
return helper(root, null, null);
}
}