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.
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.
- There is a bool variable to check whether the left child or the right child sub-tree is Perfect or not.
- 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++
#include <bits/stdc++.h>
using namespace std;
struct node {
int data;
struct node* left;
struct node* right;
};
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;
};
struct returnType {
bool isPerfect;
int height;
node* rootTree;
};
returnType findPerfectBinaryTree( struct node* root)
{
returnType rt;
if (root == NULL) {
rt.isPerfect = true ;
rt.height = 0;
rt.rootTree = NULL;
return rt;
}
returnType lv = findPerfectBinaryTree(root->left);
returnType rv = findPerfectBinaryTree(root->right);
if (lv.isPerfect && rv.isPerfect && lv.height == rv.height) {
rt.height = lv.height + 1;
rt.isPerfect = true ;
rt.rootTree = root;
return rt;
}
rt.isPerfect = false ;
rt.height = max(lv.height, rv.height);
rt.rootTree = (lv.height > rv.height ? lv.rootTree : rv.rootTree);
return rt;
}
void inorderPrint(node* root)
{
if (root != NULL) {
inorderPrint(root->left);
cout << root->data << " " ;
inorderPrint(root->right);
}
}
int main()
{
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);
struct returnType ans = findPerfectBinaryTree(root);
int h = ans.height;
cout << "Size : " << pow (2, h) - 1 << endl;
cout << "Inorder Traversal : " ;
inorderPrint(ans.rootTree);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static class node
{
int data;
node left;
node right;
};
static node newNode( int data)
{
node node = new node();
node.data = data;
node.left = null ;
node.right = null ;
return node;
};
static class returnType
{
boolean isPerfect;
int height;
node rootTree;
};
static returnType findPerfectBinaryTree(node root)
{
returnType rt = new returnType();
if (root == null )
{
rt.isPerfect = true ;
rt.height = 0 ;
rt.rootTree = null ;
return rt;
}
returnType lv = findPerfectBinaryTree(root.left);
returnType rv = findPerfectBinaryTree(root.right);
if (lv.isPerfect && rv.isPerfect &&
lv.height == rv.height)
{
rt.height = lv.height + 1 ;
rt.isPerfect = true ;
rt.rootTree = root;
return rt;
}
rt.isPerfect = false ;
rt.height = Math.max(lv.height, rv.height);
rt.rootTree = (lv.height > rv.height ?
lv.rootTree : rv.rootTree);
return rt;
}
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)
{
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 );
returnType ans = findPerfectBinaryTree(root);
int h = ans.height;
System.out.println( "Size : " +
(Math.pow( 2 , h) - 1 ));
System.out.print( "Inorder Traversal : " );
inorderPrint(ans.rootTree);
}
}
|
Python3
class Node:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def newNode(data):
node = Node( 0 )
node.data = data
node.left = None
node.right = None
return node
class returnType:
def __init__( self ):
isPerfect = 0
height = 0
rootTree = 0
def findPerfectBinaryTree(root):
rt = returnType()
if (root = = None ) :
rt.isPerfect = True
rt.height = 0
rt.rootTree = None
return rt
lv = findPerfectBinaryTree(root.left)
rv = findPerfectBinaryTree(root.right)
if (lv.isPerfect and rv.isPerfect and
lv.height = = rv.height) :
rt.height = lv.height + 1
rt.isPerfect = True
rt.rootTree = root
return rt
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
def inorderPrint(root):
if (root ! = None ) :
inorderPrint(root.left)
print (root.data, end = " " )
inorderPrint(root.right)
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 )
ans = findPerfectBinaryTree(root)
h = ans.height
print ( "Size : " , pow ( 2 , h) - 1 )
print ( "Inorder Traversal : " , end = " " )
inorderPrint(ans.rootTree)
|
C#
using System;
class GFG
{
public class node
{
public int data;
public node left;
public node right;
};
static node newNode( int data)
{
node node = new node();
node.data = data;
node.left = null ;
node.right = null ;
return node;
}
public class returnType
{
public bool isPerfect;
public int height;
public node rootTree;
};
static returnType findPerfectBinaryTree(node root)
{
returnType rt = new returnType();
if (root == null )
{
rt.isPerfect = true ;
rt.height = 0;
rt.rootTree = null ;
return rt;
}
returnType lv = findPerfectBinaryTree(root.left);
returnType rv = findPerfectBinaryTree(root.right);
if (lv.isPerfect && rv.isPerfect &&
lv.height == rv.height)
{
rt.height = lv.height + 1;
rt.isPerfect = true ;
rt.rootTree = root;
return rt;
}
rt.isPerfect = false ;
rt.height = Math.Max(lv.height, rv.height);
rt.rootTree = (lv.height > rv.height ?
lv.rootTree : rv.rootTree);
return rt;
}
static void inorderPrint(node root)
{
if (root != null )
{
inorderPrint(root.left);
Console.Write(root.data + " " );
inorderPrint(root.right);
}
}
public static void Main(String[] args)
{
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);
returnType ans = findPerfectBinaryTree(root);
int h = ans.height;
Console.WriteLine( "Size : " +
(Math.Pow(2, h) - 1));
Console.Write( "Inorder Traversal : " );
inorderPrint(ans.rootTree);
}
}
|
Javascript
<script>
class node
{
constructor(data) {
this .left = null ;
this .right = null ;
this .data = data;
}
}
function newNode(data)
{
let Node = new node(data);
return Node;
}
class returnType
{
constructor(data) {
this .isPerfect;
this .height;
this .rootTree;
}
}
function findPerfectBinaryTree(root)
{
let rt = new returnType();
if (root == null )
{
rt.isPerfect = true ;
rt.height = 0;
rt.rootTree = null ;
return rt;
}
let lv = findPerfectBinaryTree(root.left);
let rv = findPerfectBinaryTree(root.right);
if (lv.isPerfect && rv.isPerfect &&
lv.height == rv.height)
{
rt.height = lv.height + 1;
rt.isPerfect = true ;
rt.rootTree = root;
return rt;
}
rt.isPerfect = false ;
rt.height = Math.max(lv.height, rv.height);
rt.rootTree = (lv.height > rv.height ?
lv.rootTree : rv.rootTree);
return rt;
}
function inorderPrint(root)
{
if (root != null )
{
inorderPrint(root.left);
document.write(root.data + " " );
inorderPrint(root.right);
}
}
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);
let ans = findPerfectBinaryTree(root);
let h = ans.height;
document.write( "Size : " + (Math.pow(2, h) - 1) + "</br>" );
document.write( "Inorder Traversal : " );
inorderPrint(ans.rootTree);
</script>
|
Output: Size : 3
Inorder Traversal : 4 2 5
Time Complexity: O(n)
We are traversing the entire tree once.
Space Complexity: O(h)
For a given tree, we are storing the height of the tree in the returnType.