333. Largest BST Subtree

69 阅读1分钟

image.png

image.png

方法1 O(N^2)

自顶向下,先检查当前的树是不是bst,如果是bst,求子树节点数量。

  • 然后向下递归
class Solution {
    // 返回root为节点的树中的最大bst节点数量
    public int largestBSTSubtree(TreeNode root) {
        if (root == null) {
            return 0;
        }

        if (isBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE)) {
            return getNumberOfNodes(root);
        }

        return Math.max(largestBSTSubtree(root.left), largestBSTSubtree(root.right));
    }

    // 检查一棵树是否是bst
    public boolean isBST(TreeNode root, int min, int max) {
        if (root == null) {
            return true;
        }
        if (root.val >= max || root.val <= min) {
            return false;
        }
        return isBST(root.left, min, root.val) && isBST(root.right, root.val, max);
    }

    // 获取节点数量
    public int getNumberOfNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return 1 + getNumberOfNodes(root.left) + getNumberOfNodes(root.right); 
    }
}

方法2 O(N) bottm-up

新增节点信息,包含了:

  • 当前节点的子树中的最小值
  • 当前节点的子树中的最大值
  • 子树中出现过的bst的最大size

然后向上返回

class Solution {

    // 新建节点信息
    class NodeInfo {
        int subTreeMin; // 当前节点的子树中的最小值
        int subTreeMax; // 当前节点的子树中的最大值
        int maxBSTSize; // 子树中出现过的bst的最大size
        NodeInfo(int min, int max, int size) {
            this.subTreeMin = min; 
            this.subTreeMax = max;
            this.maxBSTSize = size; 
        }
    }
    
    // dfs返回当前节点的 nodeinfo
    public NodeInfo dfs(TreeNode root) {
        if (root == null) {
            // 这样设置方便叶子结点计算info,叶子结点也是bst
            return new NodeInfo(Integer.MAX_VALUE, Integer.MIN_VALUE, 0);
        }

        NodeInfo leftInfo = dfs(root.left);
        NodeInfo rightInfo = dfs(root.right);

        // 满足这个条件,说明当前节点构成了bst,更新信息
        if (root.val < rightInfo.subTreeMin && root.val > leftInfo.subTreeMax) {
            // Math.min的目的是,如果当前节点是叶子结点,之前的min是无穷大,max同理
            return new NodeInfo(Math.min(root.val, leftInfo.subTreeMin), 
                                Math.max(root.val, rightInfo.subTreeMax),
                                1 + leftInfo.maxBSTSize + rightInfo.maxBSTSize);
        }

        // 当前节点不构成bst,那么他的所有父节点,不可能构成包含当前节点在内的bst
        // 所以这么设置不让上层节点走到26行代码,但是同时也要返回下层存在的bst大小信息
        return new NodeInfo(Integer.MIN_VALUE, Integer.MAX_VALUE, 
                            Math.max(leftInfo.maxBSTSize, rightInfo.maxBSTSize));

    }

    // 返回根节点信息中的maxbstsize即可
    public int largestBSTSubtree(TreeNode root) {
        return dfs(root).maxBSTSize;
    }
}