Find the largest BST subtree in a given Binary Tree


Related: LeetCode 333 - Largest BST Subtree
Find the largest BST subtree in a given Binary Tree | GeeksforGeeks
Given a Binary Tree, write a function that returns the size of the largest subtree which is also a Binary Search Tree (BST). If the complete Binary Tree is BST, then return the size of whole tree.
Input: 
       50
     /    \
  30       60
 /  \     /  \ 
5   20   45    70
              /  \
            65    80
Output: 5
The following subtree is the maximum size BST subtree 
      60
     /  \ 
   45    70
        /  \
      65    80

https://www.geeksforgeeks.org/largest-bst-binary-tree-set-2/
The idea is based on method 3 of check if a binary tree is BST article.
A Tree is BST if following is true for every node x.
  1. The largest value in left subtree (of x) is smaller than value of x.
  2. The smallest value in right subtree (of x) is greater than value of x.
We traverse tree in bottom up manner. For every traversed node, we return maximum and minimum values in subtree rooted with it. If any node follows above properties and size of
struct Info
{
    int sz; // Size of subtree
    int max; // Min value in subtree
    int min; // Max value in subtree
    int ans; // Size of largest BST which
    // is subtree of current node
    bool isBST; // If subtree is BST
};
  
// Returns Information about subtree. The
// Information also includes size of largest
// subtree which is a BST.
Info largestBSTBT(Node* root)
{
    // Base cases : When tree is empty or it has
    // one child.
    if (root == NULL)
        return {0, INT_MIN, INT_MAX, 0, true};
    if (root->left == NULL && root->right == NULL)
        return {1, root->data, root->data, 1, true};
  
    // Recur for left subtree and right subtrees
    Info l = largestBSTBT(root->left);
    Info r = largestBSTBT(root->right);
  
    // Create a return variable and initialize its
    // size.
    Info ret;
    ret.sz = (1 + l.sz + r.sz);
  
    // If whole tree rooted under current root is
    // BST.
    if (l.isBST && r.isBST && l.max < root->data &&
            r.min > root->data)
    {
        ret.min = min(l.min, min(r.min, root->data));
        ret.max = max(r.max, max(l.max, root->data));
  
        // Update answer for tree rooted under
        // current 'root'
        ret.ans = ret.sz;
        ret.isBST = true;
  
        return ret;
    }
  
    // If whole tree is not BST, return maximum
    // of left and right subtrees
    ret.ans = max(l.ans, r.ans);
    ret.isBST = false;
  
    return ret;
}


Method 2 (Tricky and Efficient)
Key Point: PostOrderTraveral
In method 1, we traverse the tree in top down manner and do BST test for every node. If we traverse the tree in bottom up manner, then we can pass information about subtrees to the parent. The passed information can be used by the parent to do BST test (for parent node) only in constant time (or O(1) time). A left subtree need to tell the parent whether it is BST or not and also need to pass maximum value in it. So that we can compare the maximum value with the parent’s data to check the BST property. Similarly, the right subtree need to pass the minimum value up the tree. The subtrees need to pass the following information up the tree for the finding the largest BST.
1) Whether the subtree itself is BST or not (In the following code, is_bst_ref is used for this purpose)
2) If the subtree is left subtree of its parent, then maximum value in it. And if it is right subtree then minimum value in it.
3) Size of this subtree if this subtree is BST (In the following code, return value of largestBSTtil() is used for this purpose)
max_ref is used for passing the maximum value up the tree and min_ptr is used for passing minimum value up the tree
    int largestBST(Node node) {
  
        largestBSTUtil(node, val, val, val, val);
  
        return val.max_size;
    }
  
    /* largestBSTUtil() updates *max_size_ref for the size of the largest BST
     subtree.   Also, if the tree rooted with node is non-empty and a BST,
     then returns size of the tree. Otherwise returns 0.*/
    int largestBSTUtil(Node node, Value min_ref, Value max_ref,
            Value max_size_ref, Value is_bst_ref) {
  
        /* Base Case */
        if (node == null) {
            is_bst_ref.is_bst = true; // An empty tree is BST
            return 0;    // Size of the BST is 0
        }
  
        int min = Integer.MAX_VALUE;
  
        /* A flag variable for left subtree property
         i.e., max(root->left) < root->data */
        boolean left_flag = false;
  
        /* A flag variable for right subtree property
         i.e., min(root->right) > root->data */
        boolean right_flag = false;
  
        int ls, rs; // To store sizes of left and right subtrees
  
        /* Following tasks are done by recursive call for left subtree
         a) Get the maximum value in left subtree (Stored in *max_ref)
         b) Check whether Left Subtree is BST or not (Stored in *is_bst_ref)
         c) Get the size of maximum size BST in left subtree (updates *max_size) */
        max_ref.max = Integer.MIN_VALUE;
        ls = largestBSTUtil(node.left, min_ref, max_ref, max_size_ref, is_bst_ref);
        if (is_bst_ref.is_bst == true && node.data > max_ref.max) {
            left_flag = true;
        }
  
        /* Before updating *min_ref, store the min value in left subtree. So that we
         have the correct minimum value for this subtree */
        min = min_ref.min;
  
        /* The following recursive call does similar (similar to left subtree) 
         task for right subtree */
        min_ref.min = Integer.MAX_VALUE;
        rs = largestBSTUtil(node.right, min_ref, max_ref, max_size_ref, is_bst_ref);
        if (is_bst_ref.is_bst == true && node.data < min_ref.min) {
            right_flag = true;
        }
  
        // Update min and max values for the parent recursive calls
        if (min < min_ref.min) {
            min_ref.min = min;
        }
        if (node.data < min_ref.min) // For leaf nodes
        {
            min_ref.min = node.data;
        }
        if (node.data > max_ref.max) {
            max_ref.max = node.data;
        }
  
        /* If both left and right subtrees are BST. And left and right
         subtree properties hold for this node, then this tree is BST.
         So return the size of this tree */
        if (left_flag && right_flag) {
            if (ls + rs + 1 > max_size_ref.max_size) {
                max_size_ref.max_size = ls + rs + 1;
            }
            return ls + rs + 1;
        } else {
            //Since this subtree is not BST, set is_bst flag for parent calls
            is_bst_ref.is_bst = false;
            return 0;
        }

    }

Method 1 (Simple but inefficient) O(n*n)
int largestBST(struct node *root)
{
   if (isBST(root))
     return size(root);
   else
    return max(largestBST(root->left), largestBST(root->right));
}
http://leetcode.com/2010/11/largest-binary-search-tree-bst-in.html
http://www.crazyforcode.com/find-largest-bst-binary-tree/
struct node* findLargestBSTSubtree(struct node *root) {
  struct node *bstRoot = NULL;
  int min, max;
  int maxNodes = INT_MIN;
  largestBST(root, min, max, maxNodes,bstRoot);
  return bstRoot;
}
int largestBST(struct node* root, int& min, int& max, int& size,struct node* & bstRoot)
{
  if(root == NULL)
    return 0;
  int leftMin = INT_MIN, rightMin = INT_MIN;
  int leftMax = INT_MAX, rightMax = INT_MAX;
  int x,y;
  x = largestBST(root->left, leftMin, leftMax, size,bstRoot);
  y = largestBST(root->right, rightMin, rightMax, size,bstRoot);
  if(x==-1 || y ==-1)
    return -1;
  if(x==0)
  {
    leftMax = root->data;
    leftMin = root->data;
  }
  if(y==0)
  {
    rightMin = root->data;
    rightMax = root->data;
  }
  if(root->data < leftMax || root->data > rightMin)
    return -1;
  min = leftMin;
  max = rightMax;
  if(x+y+1 > size){
    size = x+y+1;
    bstRoot = root;
  }
  return x+y+1;
}
http://www.librethinking.com/2013/09/find-largest-binary-search-tree-in-tree.html
public static class TreeNodeHelper {
TreeNode node;
int nodes;
Integer maxValue;
Integer minValue;
boolean isBST;
public TreeNodeHelper() {}
public TreeNodeHelper(TreeNode node, int nodes, Integer maxValue, Integer minValue, boolean isBST) {
this.node = node;
this.nodes = nodes;
this.maxValue = maxValue;
this.minValue = minValue;
this.isBST = isBST;
}
}
 
public static TreeNodeHelper getLargestBST(TreeNode tree) {
if (tree == null) {
return new TreeNodeHelper(null, 0, null, null, false);
}
if (tree.left == null && tree.right == null) {
TreeNodeHelper helper = new TreeNodeHelper(tree, 1, tree.value, tree.value, true);
return helper;
} else {
TreeNodeHelper leftBst = getLargestBST(tree.left);
TreeNodeHelper rightBst = getLargestBST(tree.right);
 
if (!(rightBst.isBST && rightBst.minValue > tree.value)) {
rightBst.isBST = false;
}
 
if (!(leftBst.isBST && leftBst.maxValue < tree.value)) {
leftBst.isBST = false;
}
 
if (leftBst.isBST && rightBst.isBST) {
return new TreeNodeHelper(tree, rightBst.nodes + leftBst.nodes + 1, rightBst.maxValue, leftBst.minValue, true);
} else if (tree.left == null && rightBst.isBST) {
return new TreeNodeHelper(tree, ++rightBst.nodes, rightBst.maxValue, tree.value, true);
} else if (tree.right == null && leftBst.isBST) {
return new TreeNodeHelper(tree, ++leftBst.nodes, tree.value, leftBst.minValue, true);
} else {
return leftBst.nodes >= rightBst.nodes ? leftBst : rightBst;
}
}
}
The largest BST may or may not include all of its descendants.
https://github.com/xiaoningning/algorithm/blob/master/PuzzleCoding/src/LargestBSTSubtree.java
    public static class LargestBST {
        public Node node;
        public int maxNode;
        public int min;
        public int max;
    }
    // The largest BST must include all of its descendants.
    public static LargestBST largestBSTSubtree2(Node node) {
        if (node == null)
            return null;
        if (node.left == null && node.right == null) {
            return new LargestBST(node, node.size(), node.value, node.value);
        }

        LargestBST leftNode = largestBSTSubtree2(node.left);
        LargestBST rightNode = largestBSTSubtree2(node.right);

        if (leftNode != null && rightNode != null) {
            if ((node.value > leftNode.max && node.left == leftNode.node)
                    && (node.value < rightNode.min && node.right == rightNode.node)) {

                LargestBST bst = new LargestBST(node,
                        leftNode.maxNode + rightNode.maxNode + 1,
                        leftNode.min,
                        rightNode.max);

                return bst;
            } else {
                return (leftNode.maxNode > rightNode.maxNode) ? leftNode : rightNode;
            }
        } else if (leftNode != null) {
            if (node.value > leftNode.max && node.left == leftNode.node) {
                return new LargestBST(node, leftNode.maxNode + 1, leftNode.min, node.value);
            } else {
                return leftNode;
            }

        } else if (rightNode != null) {
            if (node.value < rightNode.min && node.right == rightNode.node) {
                return new LargestBST(node, rightNode.maxNode + 1, node.value, rightNode.max);
            } else {
                return rightNode;
            }
        }
        return null;
    }
http://www.librethinking.com/2013/09/find-largest-binary-search-tree-in-tree.html
https://gist.github.com/cvielma/6643658
public static class TreeNodeHelper {
TreeNode node;
int nodes; //number of nodes
Integer maxValue;
Integer minValue;
boolean isBST;
}
public static TreeNodeHelper getLargestBST(TreeNode tree) {
if (tree == null) {
return new TreeNodeHelper(null, 0, null, null, false);
}
if (tree.left == null && tree.right == null) {
TreeNodeHelper helper = new TreeNodeHelper(tree, 1, tree.value, tree.value, true);
return helper;
} else {
TreeNodeHelper leftBst = getLargestBST(tree.left);
TreeNodeHelper rightBst = getLargestBST(tree.right);
 
if (!(rightBst.isBST && rightBst.minValue > tree.value)) {
rightBst.isBST = false;
}
 
if (!(leftBst.isBST && leftBst.maxValue < tree.value)) {
leftBst.isBST = false;
}
 
if (leftBst.isBST && rightBst.isBST //? && rightBst.minValue > tree.value && && leftBst.maxValue < tree.value ) { //Both leaves are BST and BST is satisfied with current root
return new TreeNodeHelper(tree, rightBst.nodes + leftBst.nodes + 1, rightBst.maxValue, leftBst.minValue, true);
} else if (tree.left == null && rightBst.isBST) { //Only right leaf and BST is satisfied with current root
return new TreeNodeHelper(tree, ++rightBst.nodes, rightBst.maxValue, tree.value, true);
} else if (tree.right == null && leftBst.isBST) {//Only left leaf and BST is satisfied with current root.
return new TreeNodeHelper(tree, ++leftBst.nodes, tree.value, leftBst.minValue, true);
} else { //No BST is satisfied with current root
//At this point is determined that no BST can include current node, so we return
//the leaf that had the largest BST until now (if there was one)
return leftBst.nodes >= rightBst.nodes ? leftBst : rightBst;
}
}
}
Read full article from Find the largest BST subtree in a given Binary Tree | GeeksforGeeks

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts