Given the root of a binary tree, find the size of the largest subtree that is also a Binary Search Tree (BST). Note: Size of a BST means the number of nodes in the BST.
Examples:
Input:
Output: 3 Explanation: The below subtree is the maximum size BST:
Input:
Output: 1 Explanation: All the leaf nodes (2 and 3) of size 1 are valid BST.
[Naive Approach] By Checking All Subtree - O(n^2) Time and O(n) Space
A binary tree is a BST if, for its every node, all values in its left subtree are less than the node’s value, and all values in its right subtree are greater. This property must hold for every subtree in the tree.
The idea is to recursively check each subtree of a binary tree to determine whether it is a valid BST or not. If it is valid, count the nodes in that subtree and keep track of the maximum size.
C++
//Driver Code Starts#include<iostream>#include<climits>usingnamespacestd;// Node structureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=nullptr;right=nullptr;}};//Driver Code Ends// Funtion to validate bstboolisValidBst(Node*root,intminValue,intmaxValue){if(!root)returntrue;if(root->data>=maxValue||root->data<=minValue)returnfalse;returnisValidBst(root->left,minValue,root->data)&&isValidBst(root->right,root->data,maxValue);}// Funtion to calculate size of subtreeintsize(Node*root){if(!root)return0;return1+size(root->left)+size(root->right);}// Finds the size of the largest BSTintlargestBst(Node*root){if(!root)return0;// Check Subtree is valid or notif(isValidBst(root,INT_MIN,INT_MAX))returnsize(root);// Recursively call for left and right childreturnmax(largestBst(root->left),largestBst(root->right));}//Driver Code Startsintmain(){// Constructed binary tree // 5// / \ // 2 4// / \ // 1 3Node*root=newNode(5);root->left=newNode(2);root->right=newNode(4);root->left->left=newNode(1);root->left->right=newNode(3);cout<<largestBst(root)<<endl;return0;}//Driver Code Ends
Java
//Driver Code Starts// Node structureclassNode{publicintdata;publicNodeleft;publicNoderight;publicNode(intx){data=x;left=null;right=null;}}publicclassMain{//Driver Code Ends// Function to validate BSTpublicstaticbooleanisValidBst(Noderoot,intminValue,intmaxValue){if(root==null)returntrue;if(root.data>=maxValue||root.data<=minValue)returnfalse;returnisValidBst(root.left,minValue,root.data)&&isValidBst(root.right,root.data,maxValue);}// Function to calculate size of subtreepublicstaticintsize(Noderoot){if(root==null)return0;return1+size(root.left)+size(root.right);}// Finds the size of the largest BSTpublicstaticintlargestBst(Noderoot){if(root==null)return0;// Check Subtree is valid or notif(isValidBst(root,Integer.MIN_VALUE,Integer.MAX_VALUE))returnsize(root);// Recursively call for left and right childreturnMath.max(largestBst(root.left),largestBst(root.right));}//Driver Code Startspublicstaticvoidmain(String[]args){// Constructed binary tree// 5// / \// 2 4// / \// 1 3Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(4);root.left.left=newNode(1);root.left.right=newNode(3);System.out.println(largestBst(root));}}//Driver Code Ends
Python
#Driver Code Starts# Node structureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None#Driver Code Ends# Function to validate BSTdefisValidBst(root,min_value,max_value):ifnotroot:returnTrueifroot.data>=max_valueorroot.data<=min_value:returnFalsereturn(isValidBst(root.left,min_value,root.data)andisValidBst(root.right,root.data,max_value))# Function to calculate size of subtreedefsize(root):ifnotroot:return0return1+size(root.left)+size(root.right)# Finds the size of the largest BSTdeflargestBst(root):ifnotroot:return0# Check Subtree is valid or notifisValidBst(root,float('-inf'),float('inf')):returnsize(root)# Recursively call for left and right childreturnmax(largestBst(root.left),largestBst(root.right))#Driver Code Startsif__name__=='__main__':# Constructed binary tree# 5# / \# 2 4# / \# 1 3root=Node(5)root.left=Node(2)root.right=Node(4)root.left.left=Node(1)root.left.right=Node(3)print(largestBst(root))#Driver Code Ends
C#
//Driver Code StartsusingSystem;// Node structurepublicclassNode{publicintdata{get;set;}publicNodeleft{get;set;}publicNoderight{get;set;}publicNode(intx){data=x;left=null;right=null;}}publicclassGFG{//Driver Code Ends// Function to validate BSTpublicstaticboolisValidBst(Noderoot,intminValue,intmaxValue){if(root==null)returntrue;if(root.data>=maxValue||root.data<=minValue)returnfalse;returnisValidBst(root.left,minValue,root.data)&&isValidBst(root.right,root.data,maxValue);}// Function to calculate size of subtreepublicstaticintsize(Noderoot){if(root==null)return0;return1+size(root.left)+size(root.right);}// Finds the size of the largest BSTpublicstaticintlargestBst(Noderoot){if(root==null)return0;// Check Subtree is valid or notif(isValidBst(root,int.MinValue,int.MaxValue))returnsize(root);// Recursively call for left and right childreturnMath.Max(largestBst(root.left),largestBst(root.right));}//Driver Code StartspublicstaticvoidMain(){// Constructed binary tree // 5// / \// 2 4// / \// 1 3Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(4);root.left.left=newNode(1);root.left.right=newNode(3);Console.WriteLine(largestBst(root));}}//Driver Code Ends
JavaScript
//Driver Code Starts// Node structureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}//Driver Code Ends// Function to validate BSTfunctionisValidBst(root,minValue,maxValue){if(!root)returntrue;if(root.data>=maxValue||root.data<=minValue)returnfalse;returnisValidBst(root.left,minValue,root.data)&&isValidBst(root.right,root.data,maxValue);}// Function to calculate size of subtreefunctionsize(root){if(!root)return0;return1+size(root.left)+size(root.right);}// Finds the size of the largest BSTfunctionlargestBst(root){if(!root)return0;// Check Subtree is valid or notif(isValidBst(root,Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER))returnsize(root);// Recursively call for left and right childreturnMath.max(largestBst(root.left),largestBst(root.right));}//Driver Code Starts// Driver Code// Constructed binary tree // 5// / \// 2 4// / \// 1 3constroot=newNode(5);root.left=newNode(2);root.right=newNode(4);root.left.left=newNode(1);root.left.right=newNode(3);console.log(largestBst(root));//Driver Code Ends
Output
3
[Expected Approach] - Using Binary Search Tree Property - O(n) Time and O(n) Space
Intiution:
To determine if a subtree is a valid BST, we know that all values in the left subtree must be smaller than the root, and all values in the right subtree must be greater than the root. If we track the minimum and maximum values of each subtree, we can easily validate a Binary tree.
To keep track of this information and size of valid BST, we create a custom class with the following attributes:
mini = Minimum value in the subtree
maxi = Maximum value in the subtree
mxSz = Size of the largest BST in the subtree
This allows us to efficiently compute the largest BST while recursively traversing the binary tree.
Pseudo-code Idea
If the root is NULL, then return (mini = + Infinity , maxi = - Infinity , size = 0) because an empty tree is a valid BST of size 0. Otherwise, make a recursive call for the left and right subtrees to get their (mini, maxi, size) values.
If (left -> maxi) < root -> data (< right -> mini), then the current subtree is a valid BST. return min = min(left -> mini, root -> data), max = max(right -> maxi, root -> data) and size = 1 + left -> size + right -> size .
if this condition fails, it means the current subtree is not a valid BST. So, return (mini = - Infinity, maxi = + Infinity, size = max(left -> size, right -> size)).
C++
//Driver Code Starts#include<iostream>#include<climits>usingnamespacestd;// Node structureclassNode{public:intdata;Node*left;Node*right;Node(intval){data=val;left=nullptr;right=nullptr;}};//Driver Code Ends// Custom data type to keep track of Minimum,Maximum value,// and Size of the largest BSTclassBSTInfo{public:intmini;intmaxi;intmxSz;BSTInfo(intmn,intmx,intsz){mini=mn;maxi=mx;mxSz=sz;}};// Recursive Function to find maximum sizeBSTInfolargestBSTBT(Node*root){if(!root)returnBSTInfo(INT_MAX,INT_MIN,0);BSTInfoleft=largestBSTBT(root->left);BSTInforight=largestBSTBT(root->right);// Check if the current subtree is a BSTif(left.maxi<root->data&&right.mini>root->data){returnBSTInfo(min(left.mini,root->data),max(right.maxi,root->data),1+left.mxSz+right.mxSz);}returnBSTInfo(INT_MIN,INT_MAX,max(left.mxSz,right.mxSz));}// Function to return the size of the largest BSTintlargestBST(Node*root){returnlargestBSTBT(root).mxSz;}//Driver Code Startsintmain(){// Constructed binary tree // 5// / \ // 2 4// / \ // 1 3Node*root=newNode(5);root->left=newNode(2);root->right=newNode(4);root->left->left=newNode(1);root->left->right=newNode(3);cout<<largestBST(root)<<endl;return0;}//Driver Code Ends
Java
//Driver Code Starts// Node structureclassNode{intdata;Nodeleft;Noderight;Node(intval){data=val;left=null;right=null;}}//Driver Code Ends// Custom data type to keep track of Minimum, Maximum value,// and Size of the largest BSTclassBSTInfo{intmini;intmaxi;intmxSz;BSTInfo(intmn,intmx,intsz){mini=mn;maxi=mx;mxSz=sz;}}publicclassLargestBST{// Recursive Function to find maximum sizestaticBSTInfolargestBSTBT(Noderoot){if(root==null)returnnewBSTInfo(Integer.MAX_VALUE,Integer.MIN_VALUE,0);BSTInfoleft=largestBSTBT(root.left);BSTInforight=largestBSTBT(root.right);// Check if the current subtree is a BSTif(left.maxi<root.data&&right.mini>root.data){returnnewBSTInfo(Math.min(left.mini,root.data),Math.max(right.maxi,root.data),1+left.mxSz+right.mxSz);}returnnewBSTInfo(Integer.MIN_VALUE,Integer.MAX_VALUE,Math.max(left.mxSz,right.mxSz));}// Function to return the size of the largest BSTstaticintlargestBst(Noderoot){returnlargestBSTBT(root).mxSz;}//Driver Code Startspublicstaticvoidmain(String[]args){// Constructed binary tree // 5// / \// 2 4// / \// 1 3Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(4);root.left.left=newNode(1);root.left.right=newNode(3);System.out.println(largestBst(root));}}//Driver Code Ends
Python
#Driver Code Startsimportsys# Node structureclassNode:def__init__(self,val):self.data=valself.left=Noneself.right=None#Driver Code Ends# Custom data type to keep track of Minimum, Maximum value,# and Size of the largest BSTclassBSTInfo:def__init__(self,mn,mx,sz):self.mini=mnself.maxi=mxself.mxSz=sz# Recursive Function to find maximum sizedeflargestBSTBT(root):ifnotroot:returnBSTInfo(sys.maxsize,-sys.maxsize,0)left=largestBSTBT(root.left)right=largestBSTBT(root.right)# Check if the current subtree is a BSTifleft.maxi<root.dataandright.mini>root.data:returnBSTInfo(min(left.mini,root.data),max(right.maxi,root.data),1+left.mxSz+right.mxSz)returnBSTInfo(-sys.maxsize,sys.maxsize,max(left.mxSz,right.mxSz))# Function to return the size of the largest BSTdeflargestBst(root):returnlargestBSTBT(root).mxSz#Driver Code Startsif__name__=="__main__":# Constructed binary tree # 5# / \# 2 4# / \# 1 3root=Node(5)root.left=Node(2)root.right=Node(4)root.left.left=Node(1)root.left.right=Node(3)print(largestBst(root))#Driver Code Ends
C#
//Driver Code StartsusingSystem;// Node structureclassNode{publicintdata;publicNodeleft,right;publicNode(intval){data=val;left=null;right=null;}}//Driver Code Ends// Custom data type to keep track of Minimum, Maximum value,// and Size of the largest BSTclassBSTInfo{publicintmini;publicintmaxi;publicintmxSz;publicBSTInfo(intmn,intmx,intsz){mini=mn;maxi=mx;mxSz=sz;}}classLargestBST{// Recursive Function to find maximum sizestaticBSTInfolargestBSTBT(Noderoot){if(root==null)returnnewBSTInfo(int.MaxValue,int.MinValue,0);BSTInfoleft=largestBSTBT(root.left);BSTInforight=largestBSTBT(root.right);// Check if the current subtree is a BSTif(left.maxi<root.data&&right.mini>root.data){returnnewBSTInfo(Math.Min(left.mini,root.data),Math.Max(right.maxi,root.data),1+left.mxSz+right.mxSz);}returnnewBSTInfo(int.MinValue,int.MaxValue,Math.Max(left.mxSz,right.mxSz));}// Function to return the size of the largest BSTstaticintlargestBst(Noderoot){returnlargestBSTBT(root).mxSz;}//Driver Code StartsstaticvoidMain(string[]args){// Constructed binary tree // 5// / \// 2 4// / \// 1 3Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(4);root.left.left=newNode(1);root.left.right=newNode(3);Console.WriteLine(largestBst(root));}}//Driver Code Ends
JavaScript
//Driver Code Starts// Node structureclassNode{constructor(val){this.data=val;this.left=null;this.right=null;}}//Driver Code Ends// Custom data type to keep track of Minimum, Maximum value,// and Size of the largest BSTclassBSTInfo{constructor(mn,mx,sz){this.mini=mn;this.maxi=mx;this.mxSz=sz;}}// Recursive Function to find maximum sizefunctionlargestBSTBT(root){if(!root)returnnewBSTInfo(Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER,0);letleft=largestBSTBT(root.left);letright=largestBSTBT(root.right);// Check if the current subtree is a BSTif(left.maxi<root.data&&right.mini>root.data){returnnewBSTInfo(Math.min(left.mini,root.data),Math.max(right.maxi,root.data),1+left.mxSz+right.mxSz);}returnnewBSTInfo(Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Math.max(left.mxSz,right.mxSz));}// Function to return the size of the largest BSTfunctionlargestBst(root){returnlargestBSTBT(root).mxSz;}//Driver Code Starts// Driver Code// Constructed binary tree // 5// / \// 2 4// / \// 1 3letroot=newNode(5);root.left=newNode(2);root.right=newNode(4);root.left.left=newNode(1);root.left.right=newNode(3);console.log(largestBst(root));//Driver Code Ends