最大的二叉搜索子树 (二叉树递归套路)

给定一棵二叉树的头节点head,返回这颗二叉树中最大的二叉搜索子树的大小

思路

若当前不以x为头,那么看:

  1. x的左树中最大二叉搜索子树的大小
  2. x的右树中最大二叉搜索子树的大小

若当前节点为x为头,那么看经过x的树是不是二叉搜索树;
3. x的左子树是不是二叉搜索树
4. x的右子树是不是二叉搜索树
5. 左树的max < x
6. 右树的min > x
7. 左树的大小 + 右树的大小 + 1,就是当前二叉搜索子树的大小

代码实现

public class Code05_MaxSubBSTSize {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    public static int maxSubBSTSize(Node head) {
        if(head == null) {
            return 0;
        }
        return process(head).maxBSTSubtreeSize;
    }


    public static class Info {
        // 最大二叉搜索子树大小
        public int maxBSTSubtreeSize;
        // 当前树大小
        public int allSize;
        // 当前树最大值
        public int max;
        // 当前数最小值
        public int min;

        public Info(int maxBSTSubtreeSize, int allSize, int max, int min) {
            this.maxBSTSubtreeSize = maxBSTSubtreeSize;
            this.allSize = allSize;
            this.max = max;
            this.min = min;
        }
    }

    private static Info process(Node head) {
        if (head == null) {
            return null;
        }

        // 收集左树右树信息
        Info leftInfo = process(head.left);
        Info rightInfo = process(head.right);

        int allSize = 1;
        int max = head.value;
        int min = head.value;

        // 判断左右树为不为空,若不为空,则更新max,min,allSize
        if (leftInfo != null) {
            max = Math.max(leftInfo.max, max);
            min = Math.min(leftInfo.min, min);
            allSize += leftInfo.allSize;
        }
        if (rightInfo != null) {
            max = Math.max(rightInfo.max, max);
            min = Math.min(rightInfo.min, min);
            allSize += rightInfo.allSize;
        }

        int p1 = -1;  // 单独左树中最大搜索子树的大小
        if (leftInfo != null) {
            p1 = leftInfo.maxBSTSubtreeSize;
        }

        int p2 = -1;  // 单独右树中最大搜索子树的大小
        if (rightInfo != null) {
            p2 = rightInfo.maxBSTSubtreeSize;
        }

        int p3 = -1;  // 包含当前head的最大搜索子树的大小,即左右连起来
        // 首先判断左右子树是不是二叉搜索树,即对应子树的maxBSTSubtreeSize是否等于allSize
        boolean leftBST = leftInfo == null ? true : (leftInfo.maxBSTSubtreeSize == leftInfo.allSize);
        boolean rightBST = rightInfo == null ? true : (rightInfo.maxBSTSubtreeSize == rightInfo.allSize);

        // 如果左右子树都是二叉搜索子树,则连起来
        if (leftBST && rightBST) {
            // 判断左子树最大值是否小于当前根节点值
            boolean leftMaxLessHead = leftInfo == null ? true : (leftInfo.max < head.value);
            // 判断右子树最小值是否大于当前根节点值
            boolean rightMinMoreHead = rightInfo == null ? true : (rightInfo.min > head.value);
            // 如果均满足上述所有条件,才能够连接
            if (leftMaxLessHead && rightMinMoreHead) {
                int leftSize = leftInfo == null ? 0 : leftInfo.allSize;
                int rightSize = rightInfo == null ? 0 : rightInfo.allSize;
                p3 = leftSize + rightSize + 1;
            }
        }

		// 比较单独左树,单独右树,以及左右连接后最大二叉搜索子树的大小,返回最大的
        int maxBSTSubtreeSize = Math.max(p1, Math.max(p2, p3));

        return new Info(maxBSTSubtreeSize, allSize, max, min);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值