Leetcode98.验证二叉搜索树 Validate Binary Search Tree(Java)

Leetcode98.验证二叉搜索树 Validate Binary Search Tree(Java)

##Tree##, ##Depth-first Search##, ##Recursion##

验证二叉搜索树:给定一个二叉搜索树,判断其是否是一个有效的二叉搜索树

二叉搜索树的定义(特征)

  • 节点的左子树只包含小于当前节点的数
  • 节点的右子树只包含大于当前节点的数
  • 所有左子树和右子树自身必须也是二叉搜索树

二叉搜索树中不能存在值相同的结点


方法一

二叉搜索树的中序遍历是有序序列

ArrayList记录二叉搜索树的中序遍历结果,在遍历ArrayList中数的排列是否有序

时间复杂度: O(n)

class Solution {
    public ArrayList<Integer> nums = new ArrayList<>();
    public boolean isValidBST(TreeNode root) {
        dfs(root);
        for (int i = 1; i < nums.size(); i ++) {
            if (nums.get(i) <= nums.get(i - 1)) return false;
        }
        return true;
    }
    
    public void dfs(TreeNode root) {
        if (root == null) return;
        dfs(root.left);
        nums.add(root.val);
        dfs(root.right);
    }
}

方法二

对于一棵树,根节点为root,递归判断

  • 树的左子树是二叉搜索树
  • 树的右子树是二叉搜索树
  • 树根节点的值应大于左子树的最大值root.val > leftMax,且树根节点的值应小于右子树的最小值root.val > rightMin

第三条判断不能用 根据根节点与左右儿子结点的值判断结果root.val > root.left.val && root.val < root.right.val 来代替

考虑到递归每一个结点都需要返回三个变量(1.以该结点为根的树是否为二叉搜索树;2.以该结点为根的树的最大值;3.以该结点为根的树的最大值),将函数返回值设定为返回一个数组

数组维护的三个变量:1.以该结点为根的树是否为二叉搜索树;2.以该结点为根的树的最大值;3.以该结点为根的树的最大值

时间复杂度: O(n)

class Solution {
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        return dfs(root)[0] == 1;
    }
    
    public int[] dfs(TreeNode root) {
        int[] res = {1, root.val, root.val};
        if (root.left != null) {
            int[] temp = dfs(root.left);
            if (temp[0] == 0 || temp[2] >= root.val) res[0] = 0;
            res[1] = Math.min(res[1], temp[1]);
            res[2] = Math.max(res[2], temp[2]);
        }
        if (root.right != null) {
            int[] temp = dfs(root.right);
            if (temp[0] == 0 || temp[1] <= root.val) res[0] = 0;
            res[1] = Math.min(res[1], temp[1]);
            res[2] = Math.max(res[2], temp[2]);
        }
        return res;
    }
}

方法三

综合考虑方法一和方法二,采用中序遍历方法,设置变量long maxpre记录上一次遍历结点的值,根据二叉搜索树中序遍历单调性质,maxpre的中应该是所有已被遍历过的结点的最大值

因为采用中序遍历,所以maxpre应该是单调递增的,当存在root.val <= maxpre时(正在遍历的结点值小于等于之前遍历过的结点的值,不符合二叉搜索树中序遍历有序的性质),代表不符合二叉搜索树

将变量类型设置为long是因为存在值为Integer.MIN_VALUE的结点

时间复杂度: O(n)

class Solution {
    Long pre = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        boolean left = isValidBST(root.left);
        
        if (pre >= root.val) return false;
        pre = (long)root.val;  
        
        boolean right = isValidBST(root.right);        
        return left && right;
    }
}

如果节点中存在Long.MAX_VALUE时,可以记录上一次遍历的变量设置为TreeNode pre,这样根据有普适性

class Solution {
    TreeNode pre = null;
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        boolean left = isValidBST(root.left);
        
        if (pre != null && pre.val >= root.val) return false;
        pre = root;
        
        boolean right = isValidBST(root.right);
        
        return left && right;
    }
}

方法四

树的根节点为root

  • 左子树的所有结点的取值应该在(-∞,root.val)开区间之间

  • 同理,右子树的所有结点的取值应该在(root.val,+∞)之间

递归判断所有结点是否满足上述两条性质,若满足则为二叉搜索树

注意变量设置为Long

时间复杂度: O(n)

class Solution {
    public boolean isValidBST(TreeNode root) {
        return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }
    
    public boolean dfs(TreeNode root, long min, long max) {
        if (root == null) return true;
        if (root.val <= min || root.val >= max) return false;
        else return dfs(root.left, min, root.val) && dfs(root.right, root.val, max);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值