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 find it is a valid BST or not. If valid, count the nodes in that subtree and keep track of the maximum.
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 a BST or not
Size,
Minimum value
Maximum value.
Using the information returned by the left and right subtrees, find 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.
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++
#include<iostream>#include<climits>#include<algorithm>usingnamespacestd;// Node structureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=nullptr;}};// 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 BSTreturnInfo(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;}
Java
classNode{intdata;Nodeleft;Noderight;Node(intx){data=x;left=right=null;}}// Structure to store information about a subtreeclassInfo{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),Integer.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));}}
Python
importsys# Node structureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Structure to store information about a subtreeclassInfo: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,sys.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))
C#
usingSystem;// Node structureclassNode{publicintdata;publicNodeleft;publicNoderight;publicNode(intx){data=x;left=right=null;}}// 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),int.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));}}
JavaScript
// Node structureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// 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 BSTreturnnewInfo(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));