Find the largest Perfect Subtree in a given Binary Tree
Last Updated :
31 Jan, 2023
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++
// 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
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.
Similar Reads
Find the largest Complete Subtree in a given Binary Tree
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 a
13 min read
Find sum of all nodes of the given perfect binary tree
Given a positive integer L which represents the number of levels in a perfect binary tree. Given that the leaf nodes in this perfect binary tree are numbered starting from 1 to n, where n is the number of leaf nodes. And the parent node is the sum of the two child nodes. Our task is to write a progr
11 min read
Find Kth largest number in a given Binary Tree
Given a Binary Tree consisting of n nodes and a positive integer k, the task is to find the kth largest number in the given tree.Examples:Input: k = 3 Output: 5Explanation: The third largest element in the given binary tree is 5.Input: k = 1 Output: 20Explanation: The first largest element in the gi
7 min read
Check whether a given binary tree is perfect or not
Given a Binary Tree, the task is to check whether the given Binary Tree is a perfect Binary Tree or not.Note:A Binary tree is a Perfect Binary Tree in which all internal nodes have two children and all leaves are at the same level.A Perfect Binary Tree of height h has 2h â 1 nodes.Examples: Input:Ou
13 min read
Find largest subtree sum in a tree
Given a Binary Tree, the task is to find a subtree with the maximum sum in the tree.Examples: Input: Output: 28Explanation: As all the tree elements are positive, the largest subtree sum is equal to sum of all tree elements.Input: Output: 7Explanation: Subtree with largest sum is: Table of Content[E
15+ min read
Find MEX of every subtree in given Tree
Given a Generic Tree consisting of N nodes numbered from 0 to N - 1 which is rooted at node 0 and an array val[] such that the value at each node is represented by val[i], the task for each node is to find the value of MEX of its subtree. The MEX value of node V is defined as the smallest missing po
12 min read
Find the maximum node at a given level in a binary tree
Given a Binary Tree and a Level. The task is to find the node with the maximum value at that given level. The idea is to traverse the tree along depth recursively and return the nodes once the required level is reached and then return the maximum of left and right subtrees for each subsequent call.
13 min read
Construct a Perfect Binary Tree with given Height
Given an integer N, the task is to generate a perfect binary tree with height N such that each node has a value that is the same as its depth. Return the inorder traversal of the generated binary tree. A Perfect binary tree is a type of binary tree where every internal node has exactly two child nod
9 min read
Find the parent node of maximum product Siblings in given Binary Tree
Given a binary tree, the task is to find the node whose children have maximum Sibling product in the given Binary Tree. If there are multiple such nodes, return the node which has the maximum value. Examples: Input: Tree: 4 / \ 5 2 / \ 3 1 / \6 12Output: 3Explanation: For the above tree, the maximum
15+ min read
Subtree with given sum in a Binary Tree
You are given a binary tree and a given sum. The task is to check if there exists a subtree whose sum of all nodes is equal to the given sum.Examples:Input : key = 11 Output: TrueExplanation: sum of all nodes of subtree {2, 4, 5} = 11.Input : key = 6 Output: FalseExplanation: No subtree whose sum of
15 min read