Open In App

Find the largest Complete Subtree in a given Binary Tree

Last Updated : 11 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a Binary Tree, the task is to find the size and also the inorder traversal of the largest Complete sub-tree in the given Binary Tree. 
Complete Binary Tree - A Binary tree is a Complete Binary Tree if all levels are filled except possibly the last level and the last level has all keys as left as possible.

Note: All Perfect Binary Trees are Complete Binary trees but the reverse is not true. If a tree is not complete then it is also not a Perfect Binary Tree. 

Examples: 

Input:

Find-the-largest-Complete-Subtree-in-a-given-Binary-Tree-1

Output:
10
8 4 9 2 10 5 1 6 3 7
Explanation: The given tree as a whole is itself a Complete Binary Tree.

Input:

Find-the-largest-Complete-Subtree-in-a-given-Binary-Tree-2

Output:
4
10 45 60 70
Explanation: The below subtree is the largest subtree that satisfies the conditions of a Complete Binary Tree

Find-the-largest-Complete-Subtree-in-a-given-Binary-Tree-3

Approach:

The idea is to simply traverse the tree in a bottom-up manner. During the recursion, as the process moves from the child nodes back to the parent, the sub-tree information is passed up to the parent node. This information allows the parent node to perform the Complete Tree test in constant time. Both the left and right sub-trees pass details about whether they are Perfect or Complete, along with the maximum size of the largest complete binary sub-tree found so far.

To determine if the parent sub-tree is complete, the following three cases are evaluated:

  • If the left sub-tree is Perfect and the right sub-tree is Complete, and their heights are equal, then the current sub-tree (rooted at the parent) is a Complete Binary Sub-tree. Its size is equal to the sum of the sizes of the left and right sub-trees plus one (for the root).
  • If the left sub-tree is Complete and the right sub-tree is Perfect, and the height of the left sub-tree is greater than the height of the right sub-tree by one, then the current sub-tree (rooted at the parent) is a Complete Binary Sub-tree. Its size is again the sum of the sizes of the left and right sub-trees plus one (for the root). However, this sub-tree cannot be Perfect, because in this case, its left child is not perfect.
  • If neither of the above conditions is satisfied, the current sub-tree cannot be a Complete Binary Tree. In this case, the maximum size of a complete binary sub-tree found so far in either the left or right sub-tree is returned. Additionally, if the current sub-tree is not complete, it cannot be perfect either.
C++
// C++ program to find the largest Complete
// subtree of the given Binary Tree
#include <bits/stdc++.h>
using namespace std;

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

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

// Class to store details about the subtree
class SubtreeInfo {
  public:
  
    // To store if the subtree is perfect
    bool isPerfect;

    // To store if the subtree is complete
    bool isComplete;

    // Size of the subtree
    int size;

    // Root of the largest complete subtree
    Node *rootTree;
};

// Helper function to calculate height
// from the size of the subtree
int getHeight(int size) {

    // Height is calculated using the
    // formula for a perfect binary tree
    return ceil(log2(size + 1));
}

// Function to find the largest complete binary subtree
SubtreeInfo findCompleteBinaryTree(Node *root) {

    // Initialize the current subtree info
    SubtreeInfo currTree;

    // Base case: If the tree is empty
    if (root == nullptr) {
        currTree.isPerfect = true;
        currTree.isComplete = true;
        currTree.size = 0;
        currTree.rootTree = nullptr;
        return currTree;
    }

    // Recursive calls for left and right children
    SubtreeInfo leftTree = findCompleteBinaryTree(root->left);
    SubtreeInfo rightTree = findCompleteBinaryTree(root->right);

    // CASE - 1
    // If the left subtree is perfect, the right
    // is complete, and their heights are equal,
    // this subtree is complete
    if (leftTree.isPerfect && rightTree.isComplete 
        && getHeight(leftTree.size) == getHeight(rightTree.size)) {

        currTree.isComplete = true;
        currTree.isPerfect = rightTree.isPerfect;
        currTree.size = leftTree.size + rightTree.size + 1;
        currTree.rootTree = root;
        return currTree;
    }

    // CASE - 2
    // If the left subtree is complete, the right
    // is perfect, and the height of the left is
    // greater by one, this subtree is complete
    if (leftTree.isComplete && rightTree.isPerfect &&
        getHeight(leftTree.size) == getHeight(rightTree.size) + 1) {

        currTree.isComplete = true;
        currTree.isPerfect = false;
        currTree.size = leftTree.size + rightTree.size + 1;
        currTree.rootTree = root;
        return currTree;
    }

    // CASE - 3
    // Otherwise, this subtree is neither perfect
    // nor complete. Return the largest subtree
    currTree.isPerfect = false;
    currTree.isComplete = false;
    currTree.size = max(leftTree.size, rightTree.size);

    currTree.rootTree = 
    (leftTree.size > rightTree.size ? leftTree.rootTree : rightTree.rootTree);
    return currTree;
}

void inorderPrint(Node *root) {

    if (root != nullptr) {
        inorderPrint(root->left);
        cout << root->data << " ";
        inorderPrint(root->right);
    }
}

int main() {

    // Hardcoded given Binary Tree
    //        50
    //      /     \
    //     30      60
    //    /  \    /  \ 
    //   5   20  45   70
    //          /
    //        10
    Node *root = new Node(50);
    root->left = new Node(30);
    root->right = new Node(60);
    root->left->left = new Node(5);
    root->left->right = new Node(20);
    root->right->left = new Node(45);
    root->right->right = new Node(70);
    root->right->left->left = new Node(10);

    SubtreeInfo ans = findCompleteBinaryTree(root);

    cout << ans.size << endl;
    inorderPrint(ans.rootTree);

    return 0;
}
Java
// Java program to find the largest Complete
// subtree of the given Binary Tree
import java.util.*;

class Node {
    int data;
    Node left;
    Node right;

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

class SubtreeInfo {

    // To store if the subtree is perfect
    boolean isPerfect;

    // To store if the subtree is complete
    boolean isComplete;

    // Size of the subtree
    int size;

    // Root of the largest complete subtree
    Node rootTree;
}

class GfG {

    // Helper function to calculate height
    // from the size of the subtree
    static int getHeight(int size) {

        // Height is calculated using the
        // formula for a perfect binary tree
        return (int)Math.ceil(Math.log(size + 1)
                              / Math.log(2));
    }

    // Function to find the largest complete binary subtree
    static SubtreeInfo findCompleteBinaryTree(Node root) {

        // Initialize the current subtree info
        SubtreeInfo currTree = new SubtreeInfo();

        // Base case: If the tree is empty
        if (root == null) {
            currTree.isPerfect = true;
            currTree.isComplete = true;
            currTree.size = 0;
            currTree.rootTree = null;
            return currTree;
        }

        // Recursive calls for left and right children
        SubtreeInfo leftTree
            = findCompleteBinaryTree(root.left);
        SubtreeInfo rightTree
            = findCompleteBinaryTree(root.right);

        // CASE - 1
        // If the left subtree is perfect, the right
        // is complete, and their heights are equal,
        // this subtree is complete
        if (leftTree.isPerfect && rightTree.isComplete
            && getHeight(leftTree.size)
                   == getHeight(rightTree.size)) {

            currTree.isComplete = true;
            currTree.isPerfect = rightTree.isPerfect;
            currTree.size
                = leftTree.size + rightTree.size + 1;
            currTree.rootTree = root;
            return currTree;
        }

        // CASE - 2
        // If the left subtree is complete, the right
        // is perfect, and the height of the left is
        // greater by one, this subtree is complete
        if (leftTree.isComplete && rightTree.isPerfect
            && getHeight(leftTree.size)
                   == getHeight(rightTree.size) + 1) {

            currTree.isComplete = true;
            currTree.isPerfect = false;
            currTree.size
                = leftTree.size + rightTree.size + 1;
            currTree.rootTree = root;
            return currTree;
        }

        // CASE - 3
        // Otherwise, this subtree is neither perfect
        // nor complete. Return the largest subtree
        currTree.isPerfect = false;
        currTree.isComplete = false;
        currTree.size
            = Math.max(leftTree.size, rightTree.size);

        currTree.rootTree = (leftTree.size > rightTree.size
                                 ? leftTree.rootTree
                                 : rightTree.rootTree);
        return currTree;
    }

    static void inorderPrint(Node root) {

        if (root != null) {
            inorderPrint(root.left);
            System.out.print(root.data + " ");
            inorderPrint(root.right);
        }
    }

    public static void main(String[] args) {

        // Hardcoded given Binary Tree
        //        50
        //      /     \
        //     30      60
        //    /  \    /  \ 
        //   5   20  45   70
        //          /
        //        10
        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(60);
        root.left.left = new Node(5);
        root.left.right = new Node(20);
        root.right.left = new Node(45);
        root.right.right = new Node(70);
        root.right.left.left = new Node(10);

        SubtreeInfo ans = findCompleteBinaryTree(root);
        System.out.println(ans.size);
        inorderPrint(ans.rootTree);
    }
}
Python
# Python program to find the largest Complete
# subtree of the given Binary Tree
import math

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


class SubtreeInfo:

    # Initialize the subtree info
    def __init__(self):
        self.isPerfect = False
        self.isComplete = False
        self.size = 0
        self.rootTree = None

# Helper function to calculate height
# from the size of the subtree

def getHeight(size):

    # Height is calculated using the
    # formula for a perfect binary tree
    return math.ceil(math.log2(size + 1))

# Function to find the largest complete binary subtree

def findCompleteBinaryTree(root):

    # Initialize the current subtree info
    currTree = SubtreeInfo()

    # Base case: If the tree is empty
    if root is None:
        currTree.isPerfect = True
        currTree.isComplete = True
        currTree.size = 0
        currTree.rootTree = None
        return currTree

    # Recursive calls for left and right children
    leftTree = findCompleteBinaryTree(root.left)
    rightTree = findCompleteBinaryTree(root.right)

    # CASE - 1
    # If the left subtree is perfect, the right
    # is complete, and their heights are equal,
    # this subtree is complete
    if (leftTree.isPerfect and rightTree.isComplete and
            getHeight(leftTree.size) == getHeight(rightTree.size)):

        currTree.isComplete = True
        currTree.isPerfect = rightTree.isPerfect
        currTree.size = leftTree.size + rightTree.size + 1
        currTree.rootTree = root
        return currTree

    # CASE - 2
    # If the left subtree is complete, the right
    # is perfect, and the height of the left is
    # greater by one, this subtree is complete
    if (leftTree.isComplete and rightTree.isPerfect and
            getHeight(leftTree.size) == getHeight(rightTree.size) + 1):

        currTree.isComplete = True
        currTree.isPerfect = False
        currTree.size = leftTree.size + rightTree.size + 1
        currTree.rootTree = root
        return currTree

    # CASE - 3
    # Otherwise, this subtree is neither perfect
    # nor complete. Return the largest subtree
    currTree.isPerfect = False
    currTree.isComplete = False
    currTree.size = max(leftTree.size, rightTree.size)

    currTree.rootTree = (leftTree.rootTree
                         if leftTree.size > rightTree.size
                         else rightTree.rootTree)
    return currTree


def inorderPrint(root):
    if root is not None:
        inorderPrint(root.left)
        print(root.data, end=" ")
        inorderPrint(root.right)


if __name__ == "__main__":

    # Hardcoded given Binary Tree
    #        50
    #      /     \
    #     30      60
    #    /  \    /  \
    #   5   20  45   70
    #          /
    #        10
    root = Node(50)
    root.left = Node(30)
    root.right = Node(60)
    root.left.left = Node(5)
    root.left.right = Node(20)
    root.right.left = Node(45)
    root.right.right = Node(70)
    root.right.left.left = Node(10)

    ans = findCompleteBinaryTree(root)

    print(ans.size)
    inorderPrint(ans.rootTree)
C#
// C# program to find the largest Complete
// subtree of the given Binary Tree
using System;

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

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

// Class to store details about the subtree
class SubtreeInfo {

    // To store if the subtree is perfect
    public bool isPerfect;

    // To store if the subtree is complete
    public bool isComplete;

    // Size of the subtree
    public int size;

    // Root of the largest complete subtree
    public Node rootTree;
}

class GfG {

    static int GetHeight(int size) {

        // Height is calculated using the formula for a
        // perfect binary tree
        return (int)Math.Ceiling(Math.Log(size + 1)
                                 / Math.Log(2));
    }

    // Function to find the largest complete binary subtree
    static SubtreeInfo FindCompleteBinaryTree(Node root) {

        // Initialize the current subtree info
        SubtreeInfo currTree = new SubtreeInfo();

        // Base case: If the tree is empty
        if (root == null) {
            currTree.isPerfect = true;
            currTree.isComplete = true;
            currTree.size = 0;
            currTree.rootTree = null;
            return currTree;
        }

        // Recursive calls for left and right children
        SubtreeInfo leftTree
            = FindCompleteBinaryTree(root.left);
        SubtreeInfo rightTree
            = FindCompleteBinaryTree(root.right);

        // CASE - 1
        // If the left subtree is perfect, the right
        // is complete, and their heights are equal,
        // this subtree is complete
        if (leftTree.isPerfect && rightTree.isComplete
            && GetHeight(leftTree.size)
                   == GetHeight(rightTree.size)) {

            currTree.isComplete = true;
            currTree.isPerfect = rightTree.isPerfect;
            currTree.size
                = leftTree.size + rightTree.size + 1;
            currTree.rootTree = root;
            return currTree;
        }

        // CASE - 2
        // If the left subtree is complete, the right
        // is perfect, and the height of the left is
        // greater by one, this subtree is complete
        if (leftTree.isComplete && rightTree.isPerfect
            && GetHeight(leftTree.size)
                   == GetHeight(rightTree.size) + 1) {

            currTree.isComplete = true;
            currTree.isPerfect = false;
            currTree.size
                = leftTree.size + rightTree.size + 1;
            currTree.rootTree = root;
            return currTree;
        }

        // CASE - 3
        // Otherwise, this subtree is neither perfect
        // nor complete. Return the largest subtree
        currTree.isPerfect = false;
        currTree.isComplete = false;
        currTree.size
            = Math.Max(leftTree.size, rightTree.size);

        currTree.rootTree = (leftTree.size > rightTree.size
                                 ? leftTree.rootTree
                                 : rightTree.rootTree);
        return currTree;
    }

    static void InorderPrint(Node root) {

        if (root != null) {
            InorderPrint(root.left);
            Console.Write(root.data + " ");
            InorderPrint(root.right);
        }
    }

    static void Main(string[] args) {

        // Hardcoded given Binary Tree
        //        50
        //      /     \
        //     30      60
        //    /  \    /  \ 
        //   5   20  45   70
        //          /
        //        10
        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(60);
        root.left.left = new Node(5);
        root.left.right = new Node(20);
        root.right.left = new Node(45);
        root.right.right = new Node(70);
        root.right.left.left = new Node(10);

        SubtreeInfo ans = FindCompleteBinaryTree(root);
        Console.WriteLine(ans.size);
        InorderPrint(ans.rootTree);
    }
}
JavaScript
// JavaScript program to find the largest Complete
// subtree of the given Binary Tree
class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

class SubtreeInfo {
    constructor() {

        // To store if the subtree is perfect
        this.isPerfect = false;

        // To store if the subtree is complete
        this.isComplete = false;

        // Size of the subtree
        this.size = 0;

        // Root of the largest complete subtree
        this.rootTree = null;
    }
}

// Helper function to calculate height
// from the size of the subtree
function getHeight(size) {

    // Height is calculated using the
    // formula for a perfect binary tree
    return Math.ceil(Math.log2(size + 1));
}

// Function to find the largest complete binary subtree
function findCompleteBinaryTree(root) {

    // Initialize the current subtree info
    let currTree = new SubtreeInfo();

    // Base case: If the tree is empty
    if (root === null) {
        currTree.isPerfect = true;
        currTree.isComplete = true;
        currTree.size = 0;
        currTree.rootTree = null;
        return currTree;
    }

    // Recursive calls for left and right children
    let leftTree = findCompleteBinaryTree(root.left);
    let rightTree = findCompleteBinaryTree(root.right);

    // CASE - 1
    // If the left subtree is perfect, the right
    // is complete, and their heights are equal,
    // this subtree is complete
    if (leftTree.isPerfect && rightTree.isComplete
        && getHeight(leftTree.size)
               === getHeight(rightTree.size)) {
        currTree.isComplete = true;
        currTree.isPerfect = rightTree.isPerfect;
        currTree.size = leftTree.size + rightTree.size + 1;
        currTree.rootTree = root;
        return currTree;
    }

    // CASE - 2
    // If the left subtree is complete, the right
    // is perfect, and the height of the left is
    // greater by one, this subtree is complete
    if (leftTree.isComplete && rightTree.isPerfect
        && getHeight(leftTree.size)
               === getHeight(rightTree.size) + 1) {
        currTree.isComplete = true;
        currTree.isPerfect = false;
        currTree.size = leftTree.size + rightTree.size + 1;
        currTree.rootTree = root;
        return currTree;
    }

    // CASE - 3
    // Otherwise, this subtree is neither perfect
    // nor complete. Return the largest subtree
    currTree.isPerfect = false;
    currTree.isComplete = false;
    currTree.size = Math.max(leftTree.size, rightTree.size);

    currTree.rootTree = leftTree.size > rightTree.size
                            ? leftTree.rootTree
                            : rightTree.rootTree;

    return currTree;
}

function inorderPrint(root) {
    let result = [];

    function inorder(node) {
        if (node !== null) {
            inorder(node.left);
            result.push(node.data);
            inorder(node.right);
        }
    }

    inorder(root);
    console.log(result.join(" "));
}

// Hardcoded given Binary Tree
//        50
//      /     \
//     30      60
//    /  \    /  \ 
//   5   20  45   70
//          /
//        10
let root = new Node(50);
root.left = new Node(30);
root.right = new Node(60);
root.left.left = new Node(5);
root.left.right = new Node(20);
root.right.left = new Node(45);
root.right.right = new Node(70);
root.right.left.left = new Node(10);

let ans = findCompleteBinaryTree(root);

console.log(ans.size);
inorderPrint(ans.rootTree);

Output
4
10 45 60 70 

Time Complexity: O(n), as each node is visited once in the recursion, where n is the total number of nodes in the tree.
Auxiliary Space: O(h), due to the size of the stack used for recursion


Practice Tags :

Similar Reads