Given the root of a binary tree, find the size of the largest subtree that is also a Binary Search Tree (BST). A subtree is considered a BST if, for every node in the subtree:
All nodes in its left subtree have values less than the node's value.
All nodes in its right subtree have values greater than the node's value.
The subtree contains no duplicate values.
Return the number of nodes in the largest BST subtree.
Note: The size of a subtree is the total number of nodes it contains.
Examples:
Input: root = [5, 2, 4, 1, 3]
Output: 3 Explanation: The following sub-tree is a BST of size 3
Input: root = [6, 7, 3, N, 2, 2, 4]
Output: 3 Explanation: The following sub-tree is a BST of size 3:
[Naive Approach] By Checking All Subtree - O(n^2) Time and O(n) Space
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++
#include<iostream>#include<climits>usingnamespacestd;// Node structureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=nullptr;right=nullptr;}};// 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));}intmain(){// 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;}
Java
// Node structureclassNode{publicintdata;publicNodeleft;publicNoderight;publicNode(intx){data=x;left=null;right=null;}}publicclassGFG{// 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));}publicstaticvoidmain(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));}}
Python
# Node structureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# 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))if__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))
C#
usingSystem;// Node structurepublicclassNode{publicintdata{get;set;}publicNodeleft{get;set;}publicNoderight{get;set;}publicNode(intx){data=x;left=null;right=null;}}publicclassGFG{// 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));}publicstaticvoidMain(){// 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));}}
JavaScript
// Node structureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// Funtion to validate bstfunctionisValidBst(root,minValue,maxValue){if(!root)returntrue;if((minValue!==null&&root.data<=minValue)||(maxValue!==null&&root.data>=maxValue))returnfalse;returnisValidBst(root.left,minValue,root.data)&&isValidBst(root.right,root.data,maxValue);}// Funtion 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,null,null))returnsize(root);// Recursively call for left and right childreturnMath.max(largestBst(root.left),largestBst(root.right));}// 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));
Output
3
[Expected Approach] Using Binary Search Tree Property - O(n) Time and O(h) Space
The idea is to traverse the tree in postorder so that the left and right subtrees are processed before the current node. For each subtree, maintain four pieces of information: whether it is a BST, its size, its minimum value, and its maximum value. Using the information returned by the left and right subtrees, determine whether the current subtree is a BST. If it is, update its size and value range. Otherwise, propagate the size of the largest BST found in either subtree. This allows the answer to be computed in a single traversal.
Consider the following binary tree:
We process the tree in postorder, i.e., left subtree, right subtree, and then the current node.
Node 1: It is a leaf node, so it forms a BST of size 1 with minVal = 1 and maxVal = 1.
Node 3: It is also a leaf node, so it forms a BST of size 1 with minVal = 3 and maxVal = 3.
Node 2: Both left and right subtrees are BSTs, and 1 < 2 < 3. Hence, the subtree rooted at 2 is a BST of size 3 with minVal = 1 and maxVal = 3.
Node 4: It is a leaf node, so it forms a BST of size 1 with minVal = 4 and maxVal = 4.
Node 5: Although both subtrees are BSTs, the condition 5 < 4 is false. Hence, the subtree rooted at 5 is not a BST. Therefore, the largest BST size is max(3, 1) = 3.
Hence, the size of the largest BST in the given binary tree is: 3
C++
//Driver Code Starts#include<iostream>#include<climits>#include<algorithm>usingnamespacestd;// Node structureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=nullptr;}};//Driver Code Ends// Structure to store information about a subtreeclassInfo{public:boolisBST;intsize;intminVal;intmaxVal;Info(boolisBST,intsize,intminVal,intmaxVal){this->isBST=isBST;this->size=size;this->minVal=minVal;this->maxVal=maxVal;}};// Returns information about the current subtreeInfosolve(Node*root){// Empty subtree is a BSTif(root==nullptr)returnInfo(true,0,INT_MAX,INT_MIN);Infoleft=solve(root->left);Inforight=solve(root->right);// Current subtree is a BSTif(left.isBST&&right.isBST&&root->data>left.maxVal&&root->data<right.minVal){returnInfo(true,left.size+right.size+1,min(root->data,left.minVal),max(root->data,right.maxVal));}// Current subtree is not a BST//Driver Code StartsreturnInfo(false,max(left.size,right.size),INT_MIN,INT_MAX);}// Finds the size of the largest BSTintlargestBst(Node*root){returnsolve(root).size;}intmain(){// 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);return0;}//Driver Code Ends
Java
//Driver Code StartsclassNode{intdata;Nodeleft;Noderight;Node(intx){data=x;left=right=null;}}// Structure to store information about a subtree//Driver Code EndsclassInfo{booleanisBST;intsize;intminVal;intmaxVal;Info(booleanisBST,intsize,intminVal,intmaxVal){this.isBST=isBST;this.size=size;this.minVal=minVal;this.maxVal=maxVal;}}publicclassGFG{// Returns information about the current subtreestaticInfosolve(Noderoot){// Empty subtree is a BSTif(root==null)returnnewInfo(true,0,Integer.MAX_VALUE,Integer.MIN_VALUE);Infoleft=solve(root.left);Inforight=solve(root.right);// Current subtree is a BSTif(left.isBST&&right.isBST&&root.data>left.maxVal&&root.data<right.minVal){returnnewInfo(true,left.size+right.size+1,Math.min(root.data,left.minVal),Math.max(root.data,right.maxVal));}// Current subtree is not a BSTreturnnewInfo(false,Math.max(left.size,right.size),//Driver Code StartsInteger.MIN_VALUE,Integer.MAX_VALUE);}// Finds the size of the largest BSTstaticintlargestBst(Noderoot){returnsolve(root).size;}publicstaticvoidmain(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,x):self.data=xself.left=Noneself.right=None# Structure to store information about a subtree#Driver Code EndsclassInfo:def__init__(self,isBST,size,minVal,maxVal):self.isBST=isBSTself.size=sizeself.minVal=minValself.maxVal=maxVal# Returns information about the current subtreedefsolve(root):# Empty subtree is a BSTifrootisNone:returnInfo(True,0,sys.maxsize,-sys.maxsize-1)left=solve(root.left)right=solve(root.right)# Current subtree is a BSTif(left.isBSTandright.isBSTandroot.data>left.maxValandroot.data<right.minVal):returnInfo(True,left.size+right.size+1,min(root.data,left.minVal),max(root.data,right.maxVal))# Current subtree is not a BSTreturnInfo(False,max(left.size,right.size),-sys.maxsize-1,#Driver Code Startssys.maxsize)# Finds the size of the largest BSTdeflargestBst(root):returnsolve(root).sizeif__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;publicNoderight;publicNode(intx){data=x;left=right=null;}}//Driver Code Ends// Structure to store information about a subtreeclassInfo{publicboolisBST;publicintsize;publicintminVal;publicintmaxVal;publicInfo(boolisBST,intsize,intminVal,intmaxVal){this.isBST=isBST;this.size=size;this.minVal=minVal;this.maxVal=maxVal;}}classGFG{// Returns information about the current subtreestaticInfosolve(Noderoot){// Empty subtree is a BSTif(root==null)returnnewInfo(true,0,int.MaxValue,int.MinValue);Infoleft=solve(root.left);Inforight=solve(root.right);// Current subtree is a BSTif(left.isBST&&right.isBST&&root.data>left.maxVal&&root.data<right.minVal){returnnewInfo(true,left.size+right.size+1,Math.Min(root.data,left.minVal),Math.Max(root.data,right.maxVal));}// Current subtree is not a BSTreturnnewInfo(false,Math.Max(left.size,right.size),//Driver Code Startsint.MinValue,int.MaxValue);}// Finds the size of the largest BSTstaticintlargestBst(Noderoot){returnsolve(root).size;}staticvoidMain(){// 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// Structure to store information about a subtreeclassInfo{constructor(isBST,size,minVal,maxVal){this.isBST=isBST;this.size=size;this.minVal=minVal;this.maxVal=maxVal;}}// Returns information about the current subtreefunctionsolve(root){// Empty subtree is a BSTif(root===null)returnnewInfo(true,0,Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER);letleft=solve(root.left);letright=solve(root.right);// Current subtree is a BSTif(left.isBST&&right.isBST&&root.data>left.maxVal&&root.data<right.minVal){returnnewInfo(true,left.size+right.size+1,Math.min(root.data,left.minVal),Math.max(root.data,right.maxVal));}// Current subtree is not a BST//Driver Code StartsreturnnewInfo(false,Math.max(left.size,right.size),Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER);}// Finds the size of the largest BSTfunctionlargestBst(root){returnsolve(root).size;}// 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