Skip to content
Related Articles

Related Articles

Improve Article

Find the largest Perfect Subtree in a given Binary Tree

  • Difficulty Level : Medium
  • Last Updated : 07 Sep, 2021

Given a Binary Tree, the task is to find the size of largest Perfect sub-tree in the given Binary Tree. 

Perfect Binary Tree – A Binary tree is Perfect Binary Tree in which all internal nodes have two children and all leaves are at the same level.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Examples: 



Input: 
      1
    /   \
   2     3
 /  \   /
4    5 6
Output:
Size : 3
Inorder Traversal : 4 2 5
The following sub-tree is the maximum size Perfect sub-tree 
   2  
 /  \
4    5

Input:
         50
      /      \
   30         60
  /   \      /    \ 
 5    20   45      70
          /  \     /  \
         10   85  65  80
Output:
Size : 7
Inorder Traversal : 10 45 85 60 65 70 80

Approach: Simply traverse the tree in bottom up manner. Then on coming up in recursion from child to parent, we can pass information about sub-trees to the parent. The passed information can be used by the parent to do the Perfect Tree test (for parent node) only in constant time. A left sub-tree need to tell the parent whether it is a Perfect Binary Tree or not and also need to pass max height of the Perfect Binary Tree coming from left child. Similarly, the right sub-tree also needs to pass max height of Perfect Binary Tree coming from right child. 

The sub-trees need to pass the following information up the tree for finding the largest Perfect sub-tree so that we can compare the maximum height with the parent’s data to check the Perfect Binary Tree property.  

  1. There is a bool variable to check whether the left child or the right child sub-tree is Perfect or not.
  2. From left and right child calls in recursion we find out if parent sub-tree if Perfect or not by following 2 cases: 
    • If both left child and right child are perfect binary tree and have same heights then parent is also a Perfect Binary Tree with height plus one of its child.
    • If the above case is not true then parent cannot be perfect binary tree and simply returns max size Perfect Binary Tree coming from left or right sub-tree by comparing their heights.

Below is the implementation of the above approach: 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Node structure of the tree
struct node {
    int data;
    struct node* left;
    struct node* right;
};
 
// To create a new node
struct node* newNode(int data)
{
    struct node* node = (struct node*)malloc(sizeof(struct node));
    node->data = data;
    node->left = NULL;
    node->right = NULL;
    return node;
};
 
// Structure for return type of
// function findPerfectBinaryTree
struct returnType {
 
    // To store if sub-tree is perfect or not
    bool isPerfect;
 
    // Height of the tree
    int height;
 
    // Root of biggest perfect sub-tree
    node* rootTree;
};
 
// Function to return the biggest
// perfect binary sub-tree
returnType findPerfectBinaryTree(struct node* root)
{
 
    // Declaring returnType that
    // needs to be returned
    returnType rt;
 
    // If root is NULL then it is considered as
    // perfect binary tree of height 0
    if (root == NULL) {
        rt.isPerfect = true;
        rt.height = 0;
        rt.rootTree = NULL;
        return rt;
    }
 
    // Recursive call for left and right child
    returnType lv = findPerfectBinaryTree(root->left);
    returnType rv = findPerfectBinaryTree(root->right);
 
    // If both left and right sub-trees are perfect and
    // there height is also same then sub-tree root
    // is also perfect binary subtree with height
    // plus one of its child sub-trees
    if (lv.isPerfect && rv.isPerfect && lv.height == rv.height) {
        rt.height = lv.height + 1;
        rt.isPerfect = true;
        rt.rootTree = root;
        return rt;
    }
 
    // Else this sub-tree cannot be a perfect binary tree
    // and simply return the biggest sized perfect sub-tree
    // found till now in the left or right sub-trees
    rt.isPerfect = false;
    rt.height = max(lv.height, rv.height);
    rt.rootTree = (lv.height > rv.height ? lv.rootTree : rv.rootTree);
    return rt;
}
 
// Function to print the inorder traversal of the tree
void inorderPrint(node* root)
{
    if (root != NULL) {
        inorderPrint(root->left);
        cout << root->data << " ";
        inorderPrint(root->right);
    }
}
 
// Driver code
int main()
{
    // Create tree
    struct node* root = newNode(1);
    root->left = newNode(2);
    root->right = newNode(3);
    root->left->left = newNode(4);
    root->left->right = newNode(5);
    root->right->left = newNode(6);
 
    // Get the biggest sizes perfect binary sub-tree
    struct returnType ans = findPerfectBinaryTree(root);
 
    // Height of the found sub-tree
    int h = ans.height;
 
    cout << "Size : " << pow(2, h) - 1 << endl;
 
    // Print the inorder traversal of the found sub-tree
    cout << "Inorder Traversal : ";
    inorderPrint(ans.rootTree);
 
    return 0;
}

Java




// Java implementation of the approach
import java.util.*;
 
class GFG
{
     
// Node structure of the tree
static class node
{
    int data;
    node left;
    node right;
};
 
// To create a new node
static node newNode(int data)
{
    node node = new node();
    node.data = data;
    node.left = null;
    node.right = null;
    return node;
};
 
// Structure for return type of
// function findPerfectBinaryTree
static class returnType
{
 
    // To store if sub-tree is perfect or not
    boolean isPerfect;
 
    // Height of the tree
    int height;
 
    // Root of biggest perfect sub-tree
    node rootTree;
};
 
// Function to return the biggest
// perfect binary sub-tree
static returnType findPerfectBinaryTree(node root)
{
 
    // Declaring returnType that
    // needs to be returned
    returnType rt = new returnType();
 
    // If root is null then it is considered as
    // perfect binary tree of height 0
    if (root == null)
    {
        rt.isPerfect = true;
        rt.height = 0;
        rt.rootTree = null;
        return rt;
    }
 
    // Recursive call for left and right child
    returnType lv = findPerfectBinaryTree(root.left);
    returnType rv = findPerfectBinaryTree(root.right);
 
    // If both left and right sub-trees are perfect and
    // there height is also same then sub-tree root
    // is also perfect binary subtree with height
    // plus one of its child sub-trees
    if (lv.isPerfect && rv.isPerfect &&
        lv.height == rv.height)
    {
        rt.height = lv.height + 1;
        rt.isPerfect = true;
        rt.rootTree = root;
        return rt;
    }
 
    // Else this sub-tree cannot be a perfect binary tree
    // and simply return the biggest sized perfect sub-tree
    // found till now in the left or right sub-trees
    rt.isPerfect = false;
    rt.height = Math.max(lv.height, rv.height);
    rt.rootTree = (lv.height > rv.height ?
                             lv.rootTree : rv.rootTree);
    return rt;
}
 
// Function to print the
// inorder traversal of the tree
static void inorderPrint(node root)
{
    if (root != null)
    {
        inorderPrint(root.left);
        System.out.print(root.data + " ");
        inorderPrint(root.right);
    }
}
 
// Driver code
public static void main(String[] args)
{
    // Create tree
    node root = newNode(1);
    root.left = newNode(2);
    root.right = newNode(3);
    root.left.left = newNode(4);
    root.left.right = newNode(5);
    root.right.left = newNode(6);
 
    // Get the biggest sizes perfect binary sub-tree
    returnType ans = findPerfectBinaryTree(root);
 
    // Height of the found sub-tree
    int h = ans.height;
 
    System.out.println("Size : " +
                      (Math.pow(2, h) - 1));
 
    // Print the inorder traversal of the found sub-tree
    System.out.print("Inorder Traversal : ");
    inorderPrint(ans.rootTree);
}
}
 
// This code is contributed by 29AjayKumar

Python3




# Python3 implementation of above approach
 
# Tree node
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# To create a new node
def newNode(data):
 
    node = Node(0)
    node.data = data
    node.left = None
    node.right = None
    return node
 
# Structure for return type of
# function findPerfectBinaryTree
class returnType:
 
    def __init__(self):
         
        # To store if sub-tree is perfect or not
        isPerfect = 0
 
        # Height of the tree
        height = 0
 
        # Root of biggest perfect sub-tree
        rootTree = 0
 
# Function to return the biggest
# perfect binary sub-tree
def findPerfectBinaryTree(root):
 
    # Declaring returnType that
    # needs to be returned
    rt = returnType()
 
    # If root is None then it is considered as
    # perfect binary tree of height 0
    if (root == None) :
        rt.isPerfect = True
        rt.height = 0
        rt.rootTree = None
        return rt
     
    # Recursive call for left and right child
    lv = findPerfectBinaryTree(root.left)
    rv = findPerfectBinaryTree(root.right)
 
    # If both left and right sub-trees are perfect and
    # there height is also same then sub-tree root
    # is also perfect binary subtree with height
    # plus one of its child sub-trees
    if (lv.isPerfect and rv.isPerfect and
        lv.height == rv.height) :
        rt.height = lv.height + 1
        rt.isPerfect = True
        rt.rootTree = root
        return rt
     
    # Else this sub-tree cannot be a perfect binary tree
    # and simply return the biggest sized perfect sub-tree
    # found till now in the left or right sub-trees
    rt.isPerfect = False
    rt.height = max(lv.height, rv.height)
    if (lv.height > rv.height ):
        rt.rootTree = lv.rootTree
    else :
        rt.rootTree = rv.rootTree
    return rt
 
# Function to print the inorder traversal of the tree
def inorderPrint(root):
 
    if (root != None) :
        inorderPrint(root.left)
        print (root.data, end = " ")
        inorderPrint(root.right)
     
# Driver code
 
# Create tree
root = newNode(1)
root.left = newNode(2)
root.right = newNode(3)
root.left.left = newNode(4)
root.left.right = newNode(5)
root.right.left = newNode(6)
 
# Get the biggest sizes perfect binary sub-tree
ans = findPerfectBinaryTree(root)
 
# Height of the found sub-tree
h = ans.height
 
print ("Size : " , pow(2, h) - 1)
 
# Print the inorder traversal of the found sub-tree
print ("Inorder Traversal : ", end = " ")
inorderPrint(ans.rootTree)
 
# This code is contributed by Arnab Kundu

C#




// C# implementation of the approach
using System;
 
class GFG
{
     
// Node structure of the tree
public class node
{
    public int data;
    public node left;
    public node right;
};
 
// To create a new node
static node newNode(int data)
{
    node node = new node();
    node.data = data;
    node.left = null;
    node.right = null;
    return node;
}
 
// Structure for return type of
// function findPerfectBinaryTree
public class returnType
{
 
    // To store if sub-tree is perfect or not
    public bool isPerfect;
 
    // Height of the tree
    public int height;
 
    // Root of biggest perfect sub-tree
    public node rootTree;
};
 
// Function to return the biggest
// perfect binary sub-tree
static returnType findPerfectBinaryTree(node root)
{
 
    // Declaring returnType that
    // needs to be returned
    returnType rt = new returnType();
 
    // If root is null then it is considered as
    // perfect binary tree of height 0
    if (root == null)
    {
        rt.isPerfect = true;
        rt.height = 0;
        rt.rootTree = null;
        return rt;
    }
 
    // Recursive call for left and right child
    returnType lv = findPerfectBinaryTree(root.left);
    returnType rv = findPerfectBinaryTree(root.right);
 
    // If both left and right sub-trees are perfect and
    // there height is also same then sub-tree root
    // is also perfect binary subtree with height
    // plus one of its child sub-trees
    if (lv.isPerfect && rv.isPerfect &&
        lv.height == rv.height)
    {
        rt.height = lv.height + 1;
        rt.isPerfect = true;
        rt.rootTree = root;
        return rt;
    }
 
    // Else this sub-tree cannot be a perfect binary tree
    // and simply return the biggest sized perfect sub-tree
    // found till now in the left or right sub-trees
    rt.isPerfect = false;
    rt.height = Math.Max(lv.height, rv.height);
    rt.rootTree = (lv.height > rv.height ?
                             lv.rootTree : rv.rootTree);
    return rt;
}
 
// Function to print the
// inorder traversal of the tree
static void inorderPrint(node root)
{
    if (root != null)
    {
        inorderPrint(root.left);
        Console.Write(root.data + " ");
        inorderPrint(root.right);
    }
}
 
// Driver code
public static void Main(String[] args)
{
    // Create tree
    node root = newNode(1);
    root.left = newNode(2);
    root.right = newNode(3);
    root.left.left = newNode(4);
    root.left.right = newNode(5);
    root.right.left = newNode(6);
 
    // Get the biggest sizes perfect binary sub-tree
    returnType ans = findPerfectBinaryTree(root);
 
    // Height of the found sub-tree
    int h = ans.height;
 
    Console.WriteLine("Size : " +
                     (Math.Pow(2, h) - 1));
 
    // Print the inorder traversal of the found sub-tree
    Console.Write("Inorder Traversal : ");
    inorderPrint(ans.rootTree);
}
}
 
// This code is contributed by Princi Singh

Javascript




<script>
 
    // JavaScript program to print postorder
    // traversal iteratively
     
    // Node structure of the tree
    class node
    {
        constructor(data) {
           this.left = null;
           this.right = null;
           this.data = data;
        }
    }
     
    // To create a new node
    function newNode(data)
    {
        let Node = new node(data);
        return Node;
    }
     
    // Structure for return type of
    // function findPerfectBinaryTree
    class returnType
    {
        constructor(data) {
           this.isPerfect;
           this.height;
           this.rootTree;
        }
    }
 
    // Function to return the biggest
    // perfect binary sub-tree
    function findPerfectBinaryTree(root)
    {
 
        // Declaring returnType that
        // needs to be returned
        let rt = new returnType();
 
        // If root is null then it is considered as
        // perfect binary tree of height 0
        if (root == null)
        {
            rt.isPerfect = true;
            rt.height = 0;
            rt.rootTree = null;
            return rt;
        }
 
        // Recursive call for left and right child
        let lv = findPerfectBinaryTree(root.left);
        let rv = findPerfectBinaryTree(root.right);
 
        // If both left and right sub-trees are perfect and
        // there height is also same then sub-tree root
        // is also perfect binary subtree with height
        // plus one of its child sub-trees
        if (lv.isPerfect && rv.isPerfect &&
            lv.height == rv.height)
        {
            rt.height = lv.height + 1;
            rt.isPerfect = true;
            rt.rootTree = root;
            return rt;
        }
 
        // Else this sub-tree cannot be a perfect binary tree
        // and simply return the biggest sized perfect sub-tree
        // found till now in the left or right sub-trees
        rt.isPerfect = false;
        rt.height = Math.max(lv.height, rv.height);
        rt.rootTree = (lv.height > rv.height ?
                                 lv.rootTree : rv.rootTree);
        return rt;
    }
 
    // Function to print the
    // inorder traversal of the tree
    function inorderPrint(root)
    {
        if (root != null)
        {
            inorderPrint(root.left);
            document.write(root.data + " ");
            inorderPrint(root.right);
        }
    }
     
    // Create tree
    let root = newNode(1);
    root.left = newNode(2);
    root.right = newNode(3);
    root.left.left = newNode(4);
    root.left.right = newNode(5);
    root.right.left = newNode(6);
   
    // Get the biggest sizes perfect binary sub-tree
    let ans = findPerfectBinaryTree(root);
   
    // Height of the found sub-tree
    let h = ans.height;
   
    document.write("Size : " + (Math.pow(2, h) - 1) + "</br>");
   
    // Print the inorder traversal of the found sub-tree
    document.write("Inorder Traversal : ");
    inorderPrint(ans.rootTree);
 
</script>
Output: 
Size : 3
Inorder Traversal : 4 2 5

 




My Personal Notes arrow_drop_up
Recommended Articles
Page :