题解 | #找到二叉树中的最大搜索二叉子树#

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

http://www.nowcoder.com/practice/380d49d7f99242709ab4b91c36bf2acc

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

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

    /*
    1. 分析
    树形动态规划问题的前提:如果题目要求的目标是规则S,则流程一般是完成每个结点为root时的子树,在规则S下的每一个答案,
    最终答案一定在这些答案中。本题中,规则是整棵树的最大搜索二叉树(maxBST)。
    求出每一个节点作为root的子树的maxBST,最终答案一定在其中。

    1.1 第一步,可能性分析
    情况1:maxBST来自(注意,不是 “是“)X的左子树。
    情况2:maxBST来自X的右子树。
    情况3:X为root的树本身是maxBST。这需要两个条件。
        条件1,X的左子树和右子树都是maxBST。
        条件2,X.val 比左子树的val都大,比右子树的都小。
    1.2 第二步,列出信息
    根据可能性,列出所有需要的信息。为了分析前两个可能,需要左右子树上各自的maxBST的头部、大小。
    为了分析第三种可能,还需要当前结点X的值与左子树所有结点的最大值、右子树所有结点的最小值的大小。

    1.3 第三步,合并信息

    * */
    static class ReturnType{
        public Node maxBSTHead;
        public int maxBSTSize;
        public int max;
        public int min;

        public ReturnType(Node maxBSTHead, int maxBSTSize, int min, int max) {
            this.maxBSTHead = maxBSTHead;
            this.maxBSTSize = maxBSTSize;
            this.min = min;
            this.max = max;
        }
    }

    /*1、4:设计递归函数
    递归函数是处理以X为节点的情况下的***括设计递归的base case,默认直接得到左树和右树 的所有信息,
    以及把可能性做整合,并且要返回第三步的信息结构 这4个小步骤
    * */
    public static ReturnType process(Node X){
        //base case:如果子树是空树
        //min为MAX_VALUE, 保证所有的val都比它小
        //max反之
        if(X==null){
            return new ReturnType(null,0,Integer.MAX_VALUE,Integer.MIN_VALUE);
        }

        //2.1、默认得到左树的全部信息
        ReturnType lData=process(X.left);
        //2.2、默认得到右树的全部信息
        ReturnType rData=process(X.right);

        //3、信息整合
        //min       左树最小、右树最小、X的值三者中最小
        int min=Math.min(X.value,Math.min(lData.min, rData.min));
        //max
        int max=Math.max(X.value,Math.max(lData.max, rData.max));
        //情况1和2
        int maxBSTSize=Math.max(lData.maxBSTSize, rData.maxBSTSize);
        Node maxBSTHead= lData.maxBSTSize> rData.maxBSTSize? lData.maxBSTHead : rData.maxBSTHead;

        //情况3
        if(X.left==lData.maxBSTHead && X.right== rData.maxBSTHead
            && X.value> lData.max && X.value< rData.min){
            maxBSTSize= lData.maxBSTSize+ rData.maxBSTSize+1;
            maxBSTHead=X;
        }

        //信息全部收集完毕,返回
        return new ReturnType(maxBSTHead,maxBSTSi***,max);
    }


    /*dp流程:先遍历左子树收集信息,然后遍历右子树收集信息,最后在头节点做信息整合。
    因为是递归函数,所以对所有子树要求都一样,都返回ReturnType的实例
    后序遍历:时间复杂度O(N),空间复杂度O(h),h为树的深度
    * */
    public static Node getMaxBST(Node head){
        return process(head).maxBSTHead;
    }

    public static int getMaxBSTSize(Node head){
        return process(head).maxBSTSize;
    }



    public static void main(String[] args) {
        //第一行
        Scanner in=new Scanner(System.in);
        String[] input= in.nextLine().split(" ");
        int n= Integer.parseInt(input[0]);
        Node root=new Node(Integer.parseInt(input[1]));

        //构建树
        HashSet<Node> set= new HashSet<Node>();
        set.add(root);
        //遍历读取
        for (int i = 0; i < n; i++) {
            String[]nodes=in.nextLine().split(" ");
            int fatherValue=Integer.parseInt(nodes[0]);
            int leftValue=Integer.parseInt(nodes[1]);
            int rightValue=Integer.parseInt(nodes[2]);
            //遍历添加
            for (Node e:set){
                //1、比较节点
                if(e.value==fatherValue){
                    //2、建立左右节点
                    Node left= leftValue==0?null:new Node(leftValue);
                    Node right= rightValue==0?null:new Node(rightValue);
                    e.left=left;
                    e.right=right;
                    //3、左右入set
                    if(leftValue!=0){
                        set.add(left);
                    }
                    if(rightValue!=0){
                        set.add(right);
                    }
                    //4、remove
                    set.remove(e);
                    break;
                }
            }

        }

        int result= getMaxBSTSize(root);
        System.out.println(result);

    }
全部评论

相关推荐

我在朝九晚六双休的联想等你:如果我是你,身体素质好我会去参军,然后走士兵计划考研211只需要200多分。
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务