Largest BST in a Binary Tree

Last Updated : 3 Aug, 2026

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]

blobid2_1785580468

Output: 3
Explanation: The following sub-tree is a BST of size 3

blobid1_1785580468

Input: root = [6, 7, 3, N, 2, 2, 4]

blobid3_1785580468

Output: 3
Explanation: The following sub-tree is a BST of size 3:

blobid0_1785580468
Try It Yourself
redirect icon

[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>
using namespace std;

// Node structure
class Node {
public:
    int data;
    Node *left;
    Node *right;
    
    Node(int x) {
        data = x;
        left = nullptr;
      	right = nullptr;
    }
};

// Funtion to validate bst
bool isValidBst(Node *root, int minValue, int maxValue) {
    if (!root)
        return true;
    if (root->data >= maxValue || root->data <= minValue)
        return false;
    return isValidBst(root->left, minValue, root->data) && 
           isValidBst(root->right, root->data, maxValue);
}

// Funtion to calculate size of subtree
int size(Node *root) {
    if (!root)
        return 0;
    return 1 + size(root->left) + size(root->right);
}

// Finds the size of the largest BST
int largestBst(Node *root) {
    if (!root)
        return 0;
    
    // Check Subtree is valid or not
    if (isValidBst(root, INT_MIN, INT_MAX)) 
        return size(root);
  
    // Recursively call for left and right child
    return max(largestBst(root->left), 
               largestBst(root->right));
}

int main() {
  
	// Constructed binary tree 
    //         5
    //       /   \
    //      2     4
    //     / \
    //    1   3

    Node *root = new Node(5);
    root->left = new Node(2);
    root->right = new Node(4);
    root->left->left = new Node(1);
    root->left->right = new Node(3);

    cout << largestBst(root) << endl;
    return 0;
}
Java
// Node structure
class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

public class GFG {
    
    // Function to validate BST
    public static boolean isValidBst(Node root, int minValue, int maxValue) {
        if (root == null)
            return true;
        if (root.data >= maxValue || root.data <= minValue)
            return false;
        return isValidBst(root.left, minValue, root.data) &&
               isValidBst(root.right, root.data, maxValue);
    }

    // Function to calculate size of subtree
    public static int size(Node root) {
        if (root == null)
            return 0;
        return 1 + size(root.left) + size(root.right);
    }

    // Finds the size of the largest BST
    public static int largestBst(Node root) {
        if (root == null)
            return 0;

        // Check Subtree is valid or not
        if (isValidBst(root, Integer.MIN_VALUE, Integer.MAX_VALUE))
            return size(root);

        // Recursively call for left and right child
        return Math.max(largestBst(root.left), largestBst(root.right));
    }

    public static void main(String[] args) {
        
        // Constructed binary tree
        //         5
        //       /   \
        //      2     4
        //     / \
        //    1   3

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(4);
        root.left.left = new Node(1);
        root.left.right = new Node(3);

        System.out.println(largestBst(root));
    }
}
Python
# Node structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Function to validate BST
def isValidBst(root, min_value, max_value):
    if not root:
        return True
    if root.data >= max_value or root.data <= min_value:
        return False
    return (isValidBst(root.left, min_value, root.data) and
            isValidBst(root.right, root.data, max_value))

# Function to calculate size of subtree
def size(root):
    if not root:
        return 0
    return 1 + size(root.left) + size(root.right)

# Finds the size of the largest BST
def largestBst(root):
    if not root:
        return 0

    # Check Subtree is valid or not
    if isValidBst(root, float('-inf'), float('inf')):
        return size(root)

    # Recursively call for left and right child
    return max(largestBst(root.left), largestBst(root.right))

if __name__ == '__main__':
    
    # Constructed binary tree
    #         5
    #       /   \
    #      2     4
    #     / \
    #    1   3

    root = Node(5)
    root.left = Node(2)
    root.right = Node(4)
    root.left.left = Node(1)
    root.left.right = Node(3)

    print(largestBst(root))
C#
using System;

// Node structure
public class Node {
    public int data { get; set; }
    public Node left { get; set; }
    public Node right { get; set; }

    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

public class GFG {
    
    // Function to validate BST
    public static bool isValidBst(Node root, int minValue, int maxValue) {
        if (root == null)
            return true;
        if (root.data >= maxValue || root.data <= minValue)
            return false;
        return isValidBst(root.left, minValue, root.data) &&
                isValidBst(root.right, root.data, maxValue);
    }

    // Function to calculate size of subtree
    public static int size(Node root) {
        if (root == null)
            return 0;
        return 1 + size(root.left) + size(root.right);
    }

    // Finds the size of the largest BST
    public static int largestBst(Node root) {
        if (root == null)
            return 0;

        // Check Subtree is valid or not
        if (isValidBst(root, int.MinValue, int.MaxValue))
            return size(root);

        // Recursively call for left and right child
        return Math.Max(largestBst(root.left), largestBst(root.right));
    }

    public static void Main() {
        
        // Constructed binary tree 
        //         5
        //       /   \
        //      2     4
        //     / \
        //    1   3

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(4);
        root.left.left = new Node(1);
        root.left.right = new Node(3);

        Console.WriteLine(largestBst(root));
    }
}
JavaScript
// Node structure
class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// Funtion to validate bst
function isValidBst(root, minValue, maxValue) {
    if (!root)
        return true;

    if ((minValue !== null && root.data <= minValue) ||
        (maxValue !== null && root.data >= maxValue))
        return false;

    return isValidBst(root.left, minValue, root.data) &&
           isValidBst(root.right, root.data, maxValue);
}

// Funtion to calculate size of subtree
function size(root) {
    if (!root)
        return 0;

    return 1 + size(root.left) + size(root.right);
}

// Finds the size of the largest BST
function largestBst(root) {
    if (!root)
        return 0;

    // Check Subtree is valid or not
    if (isValidBst(root, null, null))
        return size(root);

    // Recursively call for left and right child
    return Math.max(largestBst(root.left),
                    largestBst(root.right));
}

// Driver code

// Constructed binary tree
//         5
//       /   \
//      2     4
//     / \
//    1   3

let root = new Node(5);
root.left = new Node(2);
root.right = new Node(4);
root.left.left = new Node(1);
root.left.right = new Node(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:

file

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>
using namespace std;

// Node structure
class Node {
public:
    int data;
    Node* left;
    Node* right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};
//Driver Code Ends


// Structure to store information about a subtree
class Info {
public:
    bool isBST;
    int size;
    int minVal;
    int maxVal;

    Info(bool isBST, int size, int minVal, int maxVal) {
        this->isBST = isBST;
        this->size = size;
        this->minVal = minVal;
        this->maxVal = maxVal;
    }
};

// Returns information about the current subtree
Info solve(Node* root) {

    // Empty subtree is a BST
    if (root == nullptr)
        return Info(true, 0, INT_MAX, INT_MIN);

    Info left = solve(root->left);
    Info right = solve(root->right);

    // Current subtree is a BST
    if (left.isBST && right.isBST &&
        root->data > left.maxVal &&
        root->data < right.minVal) {

        return Info(true, left.size + right.size + 1,
                    min(root->data, left.minVal),
                    max(root->data, right.maxVal));
    }

    // Current subtree is not a BST

//Driver Code Starts
    return Info(false, max(left.size, right.size),
                INT_MIN, INT_MAX);
}

// Finds the size of the largest BST
int largestBst(Node* root) {
    return solve(root).size;
}

int main() {

    // Constructed binary tree
    //         5
    //       /   \
    //      2     4
    //     / \
    //    1   3

    Node* root = new Node(5);
    root->left = new Node(2);
    root->right = new Node(4);
    root->left->left = new Node(1);
    root->left->right = new Node(3);

    cout << largestBst(root);

    return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
class Node {
    int data;
    Node left;
    Node right;

    Node(int x) {
        data = x;
        left = right = null;
    }
}

// Structure to store information about a subtree
//Driver Code Ends

class Info {
    boolean isBST;
    int size;
    int minVal;
    int maxVal;

    Info(boolean isBST, int size, int minVal, int maxVal) {
        this.isBST = isBST;
        this.size = size;
        this.minVal = minVal;
        this.maxVal = maxVal;
    }
}

public class GFG {

    // Returns information about the current subtree
    static Info solve(Node root) {

        // Empty subtree is a BST
        if (root == null)
            return new Info(true, 0, Integer.MAX_VALUE, Integer.MIN_VALUE);

        Info left = solve(root.left);
        Info right = solve(root.right);

        // Current subtree is a BST
        if (left.isBST && right.isBST &&
            root.data > left.maxVal &&
            root.data < right.minVal) {

            return new Info(true,
                    left.size + right.size + 1,
                    Math.min(root.data, left.minVal),
                    Math.max(root.data, right.maxVal));
        }

        // Current subtree is not a BST
        return new Info(false,
                Math.max(left.size, right.size),

//Driver Code Starts
                Integer.MIN_VALUE,
                Integer.MAX_VALUE);
    }

    // Finds the size of the largest BST
    static int largestBst(Node root) {
        return solve(root).size;
    }

    public static void main(String[] args) {

        // Constructed binary tree
        //         5
        //       /   \
        //      2     4
        //     / \
        //    1   3

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(4);
        root.left.left = new Node(1);
        root.left.right = new Node(3);

        System.out.println(largestBst(root));
    }
}
//Driver Code Ends
Python
#Driver Code Starts
import sys

# Node structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Structure to store information about a subtree
#Driver Code Ends

class Info:
    def __init__(self, isBST, size, minVal, maxVal):
        self.isBST = isBST
        self.size = size
        self.minVal = minVal
        self.maxVal = maxVal

# Returns information about the current subtree
def solve(root):

    # Empty subtree is a BST
    if root is None:
        return Info(True, 0, sys.maxsize, -sys.maxsize - 1)

    left = solve(root.left)
    right = solve(root.right)

    # Current subtree is a BST
    if (left.isBST and right.isBST and
        root.data > left.maxVal and
        root.data < right.minVal):

        return Info(True,
                    left.size + right.size + 1,
                    min(root.data, left.minVal),
                    max(root.data, right.maxVal))

    # Current subtree is not a BST
    return Info(False,
                max(left.size, right.size),
                -sys.maxsize - 1,

#Driver Code Starts
                sys.maxsize)

# Finds the size of the largest BST
def largestBst(root):
    return solve(root).size


if __name__ == "__main__":

    # Constructed binary tree
    #         5
    #       /   \
    #      2     4
    #     / \
    #    1   3

    root = 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 Starts
using System;

// Node structure
class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int x) {
        data = x;
        left = right = null;
    }
}
//Driver Code Ends


// Structure to store information about a subtree
class Info {
    public bool isBST;
    public int size;
    public int minVal;
    public int maxVal;

    public Info(bool isBST, int size, int minVal, int maxVal) {
        this.isBST = isBST;
        this.size = size;
        this.minVal = minVal;
        this.maxVal = maxVal;
    }
}

class GFG {

    // Returns information about the current subtree
    static Info solve(Node root) {

        // Empty subtree is a BST
        if (root == null)
            return new Info(true, 0, int.MaxValue, int.MinValue);

        Info left = solve(root.left);
        Info right = solve(root.right);

        // Current subtree is a BST
        if (left.isBST && right.isBST &&
            root.data > left.maxVal &&
            root.data < right.minVal) {

            return new Info(true, left.size + right.size + 1,
                Math.Min(root.data, left.minVal),
                Math.Max(root.data, right.maxVal));
        }

        // Current subtree is not a BST
        return new Info(false, Math.Max(left.size, right.size),

//Driver Code Starts
            int.MinValue, int.MaxValue);
    }

    // Finds the size of the largest BST
    static int largestBst(Node root) {
        return solve(root).size;
    }

    static void Main() {

        // Constructed binary tree
        //         5
        //       /   \
        //      2     4
        //     / \
        //    1   3

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(4);
        root.left.left = new Node(1);
        root.left.right = new Node(3);

        Console.WriteLine(largestBst(root));
    }
}
//Driver Code Ends
JavaScript
//Driver Code Starts
// Node structure
class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

//Driver Code Ends

// Structure to store information about a subtree
class Info {
    constructor(isBST, size, minVal, maxVal) {
        this.isBST = isBST;
        this.size = size;
        this.minVal = minVal;
        this.maxVal = maxVal;
    }
}

// Returns information about the current subtree
function solve(root) {

    // Empty subtree is a BST
    if (root === null)
        return new Info(true, 0, Number.MAX_SAFE_INTEGER,
                         Number.MIN_SAFE_INTEGER);

    let left = solve(root.left);
    let right = solve(root.right);

    // Current subtree is a BST
    if (left.isBST && right.isBST &&
        root.data > left.maxVal &&
        root.data < right.minVal) {

        return new Info(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 Starts
    return new Info(false,
        Math.max(left.size, right.size),
        Number.MIN_SAFE_INTEGER,
        Number.MAX_SAFE_INTEGER);
}

// Finds the size of the largest BST
function largestBst(root) {
    return solve(root).size;
}

// Driver code

// Constructed binary tree
//         5
//       /   \
//      2     4
//     / \
//    1   3

let root = new Node(5);
root.left = new Node(2);
root.right = new Node(4);
root.left.left = new Node(1);
root.left.right = new Node(3);

console.log(largestBst(root));
//Driver Code Ends

Output
3
Comment