首页 > 试题广场 >

找到二叉树中的最大搜索二叉子树

[编程题]找到二叉树中的最大搜索二叉子树
  • 热度指数:2999 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一颗二叉树,已知其中所有节点的值都不一样,找到含有节点最多的搜索二叉子树,输出该子树总节点的数量。
搜索二叉树是指对于二叉树的任何一个节点,都大于其左子树中的全部节点,但是小于其右子树中的全部节点。

输入描述:
第一行输入两个整数 n 和 root,n 表示二叉树的总节点个数,root 表示二叉树的根节点。

以下 n 行每行三个整数 fa,lch,rch,表示 fa 的左儿子为 lch,右儿子为 rch。(如果 lch 为 0 则表示 fa 没有左儿子,rch同理)

ps:节点的编号就是节点的值。


输出描述:

示例1

输入

3 2
2 1 3
1 0 0
3 0 0

输出

3
树型DP,使用二叉树的递归套路,根据是否要将当前结点纳入搜索二叉树划分可能性。需要向左子树和右子树要五个信息:
  1. 子树的最大二叉搜索树的根结点;
  2. 子树的最大二叉搜索树的节点数量;
  3. 子树是否是二叉搜索树;
  4. 子树的节点最小值;
  5. 子树的节点最大值。
将左右子树的以上五个信息整合为当前节点的五个信息,以供更上层的节点使用。最终根节点得到的最大二叉搜索树节点数量就是我们要求的答案。整个过程其实就是二叉树的后续遍历,中间的比较过程都是O(1)的时间复杂度,算法的整体时间复杂度为O(N)。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;

class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode(int val) {
        this.val = val;
    }
}

class Info {
    public TreeNode maxBSTHead;
    public int maxBSTSize;
    public boolean isBST;
    public int min;
    public int max;
    public Info(TreeNode maxBSTHead, int maxBSTSize, boolean isBST, int min, int max) {
        this.maxBSTHead = maxBSTHead;
        this.maxBSTSize = maxBSTSize;
        this.isBST = isBST;
        this.min = min;
        this.max = max;
    }
}

public class Main{
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        HashMap<Integer, TreeNode> map = new HashMap<>();
        String[] params = br.readLine().split(" ");
        int n = Integer.parseInt(params[0]), rootVal = Integer.parseInt(params[1]);
        // 构建二叉树
        TreeNode root = new TreeNode(rootVal);
        map.put(rootVal, root);
        for(int i = 0; i < n; i++){
            params = br.readLine().split(" ");
            int nodeVal = Integer.parseInt(params[0]);
            int leftVal = Integer.parseInt(params[1]);
            int rightVal = Integer.parseInt(params[2]);
            TreeNode node = map.get(nodeVal);
            if(leftVal != 0) {
                node.left = new TreeNode(leftVal);
                map.put(leftVal, node.left);
            }
            if(rightVal != 0) {
                node.right = new TreeNode(rightVal);
                map.put(rightVal, node.right);
            }
        }
        // 求解
        System.out.println(process(root).maxBSTSize);
    }
    
    private static Info process(TreeNode node) {
        if(node == null) return null;
        Info leftInfo = process(node.left);
        Info rightInfo = process(node.right);
        TreeNode maxBSTHead = null;
        int maxBSTSize = 0;
        int max = node.val;
        int min = node.val;
        // 最值在左右信息不为空的时候需要比较更新
        if(leftInfo != null){
            maxBSTHead = leftInfo.maxBSTHead;
            maxBSTSize = leftInfo.maxBSTSize;
            max = Math.max(max, leftInfo.max);
            min = Math.min(min, leftInfo.min);
        }
        if(rightInfo != null){
            if(rightInfo.maxBSTSize > maxBSTSize){
                maxBSTHead = rightInfo.maxBSTHead;
                maxBSTSize = rightInfo.maxBSTSize;
            }
            max = Math.max(max, rightInfo.max);
            min = Math.min(min, rightInfo.min);
        }
        boolean isBST = false;
        // 左右子树都是BST且能够和当前节点连起来时,能够形成一个以当前节点为根的更大的BST
        if((leftInfo == null || (leftInfo.isBST && leftInfo.max < node.val)) && (rightInfo == null || (rightInfo.isBST && rightInfo.min > node.val))){
            isBST = true;
            maxBSTHead = node;
            maxBSTSize = (leftInfo != null? leftInfo.maxBSTSize: 0) + (rightInfo != null? rightInfo.maxBSTSize: 0) + 1;
        }
        return new Info(maxBSTHead, maxBSTSize, isBST, min, max);
    }
}

发表于 2021-11-26 18:47:35 回复(0)