zoukankan      html  css  js  c++  java
  • 333. Largest BST Subtree

    nlgn就不说了。。说n的方法。
    这个题做了好久。

    一开始想到的是post-order traversal.

    左右都是BST,然后自己也是BST,返还长度是左+右+自己(1)。

    左右其中一个不是,或者自己不是的话,返还-1.

    第一次尝试忽略了跳级问题,判断自己能不能和左右子树组成BST的情况是,自己必须比左子树的最大值大,比右子树的最小值小。。所以害的自己造个变量记录最大最小值。

    提交的时候改了半天,主要问题在于更新最大最小但是会后,既要以子树更新,又要以自己的VAL更新,一开始忽略了其中一种。。

    public class Solution 
    {
        
        public class MaxMin
        {
            int max = Integer.MIN_VALUE;
            int min = Integer.MAX_VALUE;
            public MaxMin(int max, int min)
            {
                this.max = max;
                this.min = min;
            }
        }
        
        int a = 1;
        public int largestBSTSubtree(TreeNode root) 
        {
            
            if(root == null) return 0;
            MaxMin r = new MaxMin(Integer.MIN_VALUE,Integer.MAX_VALUE);
            int res = helper(root,r);
            
            a = Math.max(res,a);
            
            return a;
            
            
        }
        
        public int helper(TreeNode root, MaxMin m)
        {
            if(root == null) return 0;
            if(root.left == null && root.right == null)
            {
                m.max = Math.max(m.max,root.val);
                m.min = Math.min(m.min,root.val);
                return 1;
            }
            
            MaxMin m1 = new MaxMin(m.max,m.min);
            MaxMin m2 = new MaxMin(m.max,m.min);
            
            
            
            int left = helper(root.left,m1);
            int right = helper(root.right,m2);
            int res = 1;
    
            m.max = Math.max(m.max,root.val);
            m.min = Math.min(m.min,root.val);
    
            
            
            m.max = Math.max(Math.max(m.max,m1.max),m2.max);
            m.min = Math.min(Math.min(m.min,m1.min),m2.min);
            
            if(left != -1 && right != -1)
            {
    
                if(root.val < m2.min && root.val > m1.max)
                {
                    res += left + right;
                    a = Math.max(res,a);
                    return res;
                }
                else return -1;
                
            }
            else return -1;
    
        }
    
    }
    

    另一种N的尝试是,做一个in-order traversal,找其中的递增组合。不过仔细想想犹豫结构不确定,不一定是completed tree所以无法判定。。



    二刷。

    这个题做了他妈好久。

    回头看一刷觉得太繁琐了,肯定有问题,但是又不想在基础上改。

    像题目说的,直白的做法是每个NODE都call一次valid BST,这样是O(nlgn).

    现在要求O(n),只能遍历一次。那肯定是bottom-up,用post-order traversal.

    有一点要注意的是,subtree得到底才行,必须包含最下的leaves.

    我们需要传到上面的信息有这么几个:

    1. 我是不是BST,以便于上面判断他是不是BST.

    2. 我作为BST的最大Size,以便于上面进行左右取舍,或相加(如果左右+自己都是BST)

    3. 我的取值区间,最大值和最小值。对于上面的parent node来说,他得比左支最大值大,比右支最小值小。

    需要传递的信息有3个,自己建个新的class比较方便。

    学到的一个tricky是用size正负来表示1),是否是BST。负数就说明我不是BST。

    Time: O(n) DFS post-order
    Space: O(n) for Stack in memory

    public class Solution {
        public class Node {
            int max;
            int min;
            int num;
            public Node(int max, int min, int num) {
                this.max = max;
                this.min = min;
                this.num = num;
            }
        }
        
        public int largestBSTSubtree(TreeNode root) {
            return Math.abs(dfs(root).num);
        }
        
        public Node dfs(TreeNode root) {
            if (root == null) return new Node(Integer.MIN_VALUE, Integer.MAX_VALUE, 0);
            
            Node leftRes = dfs(root.left);
            Node rightRes = dfs(root.right);
            
            int curMin = Math.min(root.val, leftRes.min);
            int curMax = Math.max(root.val, rightRes.max);
            
            
            if (root.val <= leftRes.max || root.val >= rightRes.min || leftRes.num < 0 || rightRes.num < 0) {
                //System.out.println(leftRes.num + " " + rightRes.num);
                return new Node(curMax, curMin, Math.max(Math.abs(leftRes.num), Math.abs(rightRes.num)) * -1);
            } else {
                return new Node(curMax, curMin, leftRes.num + rightRes.num + 1);
            }
            
        }
    }
    

    2个判断不太好理解,着重说一下。

        if (root.val <= leftRes.max || root.val >= rightRes.min || leftRes.num < 0 || rightRes.num < 0) {
                return new Node(curMax, curMin, Math.max(Math.abs(leftRes.num), Math.abs(rightRes.num)) * -1);
            } 
    

    这说明不符合BST规定。
    root.val <= 左支最大值. root.val >= 右支最小值.
    左支BST的SIZE < 0 或者 右支BST的Size < 0

    这个时候返还的Node要注意。
    curMax和curMin说实话其实无所谓,返还什么都行,因为第三个值要返还负数。
    第三个值首先要确定返还负数,最后乘以-1。
    判断前取绝对值Math.abs(leftRes.num)是代表:
    子树最大subTree的size,不一定就是root.left的值,可能还要往下。
    正负号代表当前子树(root.left)是否是BST.

    else是判断成功,左右都是,自己也是,那么显然左+右+1就行了。

  • 相关阅读:
    vue中根据手机类型判断是安卓、微信或IOS跳转相应下载页面
    冒泡排序、数组去重
    vue2中component父子组件传递数据props的使用
    filter 在CSS用的效果
    纪念一下——做事要踏实
    要先学会做人,再做事
    2014再见,2013你好!
    --initialize specified but the data directory has files in it. Aborting. 解决
    Unity 发生 System.TypeInitializationException: “”的类型初始值设定项引发异常。的错误
    C#和delphi交互传结构体的delphi接收不到问题
  • 原文地址:https://www.cnblogs.com/reboot329/p/5951425.html
Copyright © 2011-2022 走看看