package com.interview.tree;
/**
* Date 07/20/2014
* @author tusroy
*
* Video link - https://youtu.be/4fiDs7CCxkc
*
* Given a binary tree, find size of largest binary search subtree in this
* binary tree.
*
* Traverse tree in post order fashion. Left and right nodes return 4 piece
* of information to root which isBST, size of max BST, min and max in those
* subtree.
* If both left and right subtree are BST and this node data is greater than max
* of left and less than min of right then it returns to above level left size +
* right size + 1 and new min will be min of left side and new max will be max of
* right side.
*
* References:
* http://www.geeksforgeeks.org/find-the-largest-subtree-in-a-tree-that-is-also-a-bst/
* https://leetcode.com/problems/largest-bst-subtree/
*/
public class LargestBSTInBinaryTree {
public int largestBST(Node root){
MinMax m = largest(root);
return m.size;
}
private MinMax largest(Node root){
//if root is null return min as Integer.MAX and max as Integer.MIN
if(root == null){
return new MinMax();
}
//postorder traversal of tree. First visit left and right then
//use information of left and right to calculate largest BST.
MinMax leftMinMax = largest(root.left);
MinMax rightMinMax =largest(root.right);
MinMax m = new MinMax();
//if either of left or right subtree says its not BST or the data
//of this node is not greater/equal than max of left and less than min of right
//then subtree with this node as root will not be BST.
//Return false and max size of left and right subtree to parent
if(leftMinMax.isBST == false || rightMinMax.isBST == false || (leftMinMax.max > root.data || rightMinMax.min <= root.data)){
m.isBST = false;
m.size = Math.max(leftMinMax.size, rightMinMax.size);
return m;
}
//if we reach this point means subtree with this node as root is BST.
//Set isBST as true. Then set size as size of left + size of right + 1.
//Set min and max to be returned to parent.
m.isBST = true;
m.size = leftMinMax.size + rightMinMax.size + 1;
//if root.left is null then set root.data as min else
//take min of left side as min
m.min = root.left != null ? leftMinMax.min : root.data;
//if root.right is null then set root.data as max else
//take max of right side as max.
m.max = root.right != null ? rightMinMax.max : root.data;
return m;
}
public static void main(String args[]){
LargestBSTInBinaryTree lbi = new LargestBSTInBinaryTree();
ConstructTreeFromInOrderPreOrder ctf = new ConstructTreeFromInOrderPreOrder();
//this is just to create a binary tree.
int inorder[] = {-7,-6,-5,-4,-3,-2,1,2,3,16,6,10,11,12,14};
int preorder[] = {3,-2,-3,-4,-5,-6,-7,1,2,16,10,6,12,11,14};
Node root = ctf.createTree(inorder, preorder);
int largestBSTSize = lbi.largestBST(root);
System.out.println("Size of largest BST is " + largestBSTSize);
assert largestBSTSize == 8;
}
}
/**
* Object of this class holds information which child passes back
* to parent node.
*/
class MinMax{
int min;
int max;
boolean isBST;
int size ;
MinMax(){
min = Integer.MAX_VALUE;
max = Integer.MIN_VALUE;
isBST = true;
size = 0;
}
}