LeetCode 333. Largest BST Subtree

题目

找出二叉树中最大的子树,该子树为二叉搜索树。所谓最大的子树就是指结点数目最多的子树。

分析

该题目是要找出二叉树中最大的子树,该子树必须是二叉搜索树(BST)。子树的概念需要重点关注一下,以下面一棵二叉树为例

         ____10____
        /          \
      __5_         15_
     /    \           \
     1     8           7

那么该二叉树最大的为BST的子树应该算subtree(1)还是subtree(2)呢?

         ____ 10____
        /           \
      __5_          15     -------- subtree (1)
     /    \
     1     8 
      __5_
     /    \               -------- subtree (2)
     1     8 

根据维基百科对子树的定义,一棵二叉树T的子树由T的某个结点和该结点所有的后代构成。也就是说,该题目中,subtree(2)才是正确的答案,因为subtree(1)不包含结点7,不满足子树的定义。

基本解法—自顶向下

最自然的解法是以根结点开始遍历二叉树所有的结点,判定以当前结点为根的子树是否是BST,如果是,则该结点为根的BST就是最大的BST。如果不是,递归调用左右子树,返回其中包含较多结点的子树。

此处代码略。。。。。。。

优化方法—自底向上

由于自顶向下的方法每次都要调用isBST来判断当前结点为根结点的子树是否是二叉搜索树,每次调用时间为O(n),其实这里面有些重复的判断。如果采用自底向上的方法,我们在判断上面结点为根的子树是否是BST之前已经知道底部结点为根的子树是否是BST。因此只要以底部结点为根的子树不是BST,则以它上面结点为根的子树一定不是BST。

判定一颗树是否是BST的方法如下:

1)每个结点的左右子树都是BST

2)每个结点的值大于左子树的最大值

3)每个结点的值小于右子树的最小值

因此采用自底向上的方法时,我们需要向上传递一些信息,包括子树的最大值和最小值以及子树的大小。显然,树的大小=左子树大小+右子树大小+1。

package middle;

/**
 */
class Solution {

    public int largestBSTSubtree(TreeNode root) {
        if (root == null) return 0;
        Result result = dfs(root);

        return result.getNodeSize();
    }

    public Result dfs(TreeNode root) {

        if (root == null) {
            return new Result(true, 0, null, null);

        }
        if (root.left == null && root.right == null) {
            return new Result(true, 1, root.val, root.val);
        }

        Result left = dfs(root.left);
        Result right = dfs(root.right);
        if ((!left.isBST) || (!right.isBST) || (left.maxVal != null && left.maxVal >= root.val)
            || (right.minVal != null && right.minVal <= root.val)) {

            return new Result(false, Math.max(left.getNodeSize(), right.getNodeSize()), null, null);
        }

        return new Result(true, 1 + left.nodeSize + right.nodeSize, left.minVal == null ? root.val : left.minVal,
                          right.maxVal == null ? root.val : right.maxVal);

    }

    public class TreeNode {

        int      val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }

    public class Result {

        Boolean isBST;   // 是否是BST
        int     nodeSize;// 节点数量
        Integer maxVal;  // 最大值
        Integer minVal;  // 最小值

        public Result(Boolean isBST, int nodeSize, Integer minVal, Integer maxVal) {
            this.isBST = isBST;
            this.nodeSize = nodeSize;
            this.maxVal = maxVal;
            this.minVal = minVal;
        }

        public Boolean getBST() {
            return isBST;
        }

        public int getNodeSize() {
            return nodeSize;
        }

        public Integer getMaxVal() {
            return maxVal;
        }

        public Integer getMinVal() {
            return minVal;
        }
    }
}

参考:

https://www.cnblogs.com/rookielet/p/10740627.html

https://www.xuebuyuan.com/852689.html

点赞