在给定的二叉树中找到最大的完整子树
给定一棵二叉树,任务是找到给定二叉树中最大完整子树的大小。
完全二叉树——如果所有层都被完全填满,除了可能的最后一层并且最后一层的所有键都尽可能离开,那么二叉树就是完全二叉树。
注意:所有完美二叉树都是完全二叉树,但不正确。如果一棵树不完整,那么它也不是完美二叉树。
例子:
Input:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
Output:
Size : 10
Inorder Traversal : 8 4 9 2 10 5 1 6 3 7
The given tree a complete binary tree.
Input:
50
/ \
30 60
/ \ / \
5 20 45 70
/
10
Output:
Size : 4
Inorder Traversal : 10 45 60 70
方法:简单地以自下而上的方式遍历树。然后在从子树到父树的递归中,我们可以将有关子树的信息传递给父树。传递的信息只能在恒定时间内被父节点用于完成树测试(针对父节点)。左子树和右子树都需要告诉父信息它们是否完美,是否完整,它们还需要返回到目前为止找到的完整二叉树的最大大小。
子树需要将以下信息向上传递以找到最大的完整子树,以便我们可以将最大大小与父级的数据进行比较以检查完整二叉树的属性。
- 有一个 bool 变量来检查左子或右子子树是否完美和完整。
- 从递归的左右子调用中,我们通过以下3种情况确定父子树是否完整:
- 如果左子树是完美的并且右子树是完整的并且高度也相同,则子树根也是完整的二叉子树,其大小等于左右子树的总和加一(对于当前根)。
- 如果左子树是完整的并且右是完美的并且左的高度比右大一,那么子树根是完整的二叉子树,其大小等于左右子树的总和加一(对于当前根)。并且根子树不能是完美的二叉子树,因为在这种情况下它的左孩子不是完美的。
- 否则这个子树不能是一个完整的二叉树,并且简单地返回迄今为止在左子树或右子树中找到的最大大小的完整子树。如果树不完整,那么它也不完美。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
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;
// To store if sub-tree is complete or not
bool isComplete;
// size of the tree
int size;
// Root of biggest complete sub-tree
node* rootTree;
};
// helper function that returns height
// of the tree given size
int getHeight(int size)
{
return ceil(log2(size + 1));
}
// Function to return the biggest
// complete binary sub-tree
returnType findCompleteBinaryTree(struct node* root)
{
// Declaring returnType that
// needs to be returned
returnType rt;
// If root is NULL then it is considered as both
// perfect and complete binary tree of size 0
if (root == NULL) {
rt.isPerfect = true;
rt.isComplete = true;
rt.size = 0;
rt.rootTree = NULL;
return rt;
}
// Recursive call for left and right child
returnType lv = findCompleteBinaryTree(root->left);
returnType rv = findCompleteBinaryTree(root->right);
// CASE - A
// If left sub-tree is perfect and right is complete and
// there height is also same then sub-tree root
// is also complete binary sub-tree with size equal to
// sum of left and right subtrees plus one for current root
if (lv.isPerfect == true && rv.isComplete == true
&& getHeight(lv.size) == getHeight(rv.size)) {
rt.isComplete = true;
// If right sub-tree is perfect then
// root is also perfect
rt.isPerfect = (rv.isPerfect ? true : false);
rt.size = lv.size + rv.size + 1;
rt.rootTree = root;
return rt;
}
// CASE - B
// If left sub-tree is complete and right is perfect and the
// height of left is greater than right by one then sub-tree root
// is complete binary sub-tree with size equal to
// sum of left and right subtrees plus one for current root.
// But sub-tree cannot be perfect binary sub-tree.
if (lv.isComplete == true && rv.isPerfect == true
&& getHeight(lv.size) == getHeight(rv.size) + 1) {
rt.isComplete = true;
rt.isPerfect = false;
rt.size = lv.size + rv.size + 1;
rt.rootTree = root;
return rt;
}
// CASE - C
// Else this sub-tree cannot be a complete binary tree
// and simply return the biggest sized complete sub-tree
// found till now in the left or right sub-trees
rt.isPerfect = false;
rt.isComplete = false;
rt.size = max(lv.size, rv.size);
rt.rootTree = (lv.size > rv.size ? 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 the tree
struct node* root = newNode(50);
root->left = newNode(30);
root->right = newNode(60);
root->left->left = newNode(5);
root->left->right = newNode(20);
root->right->left = newNode(45);
root->right->right = newNode(70);
root->right->left->left = newNode(10);
// Get the biggest sized complete binary sub-tree
struct returnType ans = findCompleteBinaryTree(root);
cout << "Size : " << ans.size << endl;
// Print the inorder traversal of the found sub-tree
cout << "Inorder Traversal : ";
inorderPrint(ans.rootTree);
return 0;
}
Java
// Java implementation of the approach
class Sol
{
// 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;
// To store if sub-tree is complete or not
boolean isComplete;
// size of the tree
int size;
// Root of biggest complete sub-tree
node rootTree;
};
// helper function that returns height
// of the tree given size
static int getHeight(int size)
{
return (int)Math.ceil(Math.log(size + 1)/Math.log(2));
}
// Function to return the biggest
// complete binary sub-tree
static returnType findCompleteBinaryTree(node root)
{
// Declaring returnType that
// needs to be returned
returnType rt=new returnType();
// If root is null then it is considered as both
// perfect and complete binary tree of size 0
if (root == null)
{
rt.isPerfect = true;
rt.isComplete = true;
rt.size = 0;
rt.rootTree = null;
return rt;
}
// Recursive call for left and right child
returnType lv = findCompleteBinaryTree(root.left);
returnType rv = findCompleteBinaryTree(root.right);
// CASE - A
// If left sub-tree is perfect and right is complete and
// there height is also same then sub-tree root
// is also complete binary sub-tree with size equal to
// sum of left and right subtrees plus one for current root
if (lv.isPerfect == true && rv.isComplete == true
&& getHeight(lv.size) == getHeight(rv.size))
{
rt.isComplete = true;
// If right sub-tree is perfect then
// root is also perfect
rt.isPerfect = (rv.isPerfect ? true : false);
rt.size = lv.size + rv.size + 1;
rt.rootTree = root;
return rt;
}
// CASE - B
// If left sub-tree is complete and right is perfect and the
// height of left is greater than right by one then sub-tree root
// is complete binary sub-tree with size equal to
// sum of left and right subtrees plus one for current root.
// But sub-tree cannot be perfect binary sub-tree.
if (lv.isComplete == true && rv.isPerfect == true
&& getHeight(lv.size) == getHeight(rv.size) + 1)
{
rt.isComplete = true;
rt.isPerfect = false;
rt.size = lv.size + rv.size + 1;
rt.rootTree = root;
return rt;
}
// CASE - C
// Else this sub-tree cannot be a complete binary tree
// and simply return the biggest sized complete sub-tree
// found till now in the left or right sub-trees
rt.isPerfect = false;
rt.isComplete = false;
rt.size = Math.max(lv.size, rv.size);
rt.rootTree = (lv.size > rv.size ? 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 the tree
node root = newNode(50);
root.left = newNode(30);
root.right = newNode(60);
root.left.left = newNode(5);
root.left.right = newNode(20);
root.right.left = newNode(45);
root.right.right = newNode(70);
root.right.left.left = newNode(10);
// Get the biggest sized complete binary sub-tree
returnType ans = findCompleteBinaryTree(root);
System.out.println( "Size : " + ans.size );
// Print the inorder traversal of the found sub-tree
System.out.print("Inorder Traversal : ");
inorderPrint(ans.rootTree);
}
}
// This code is contributed by Arnab Kundu
Python3
# Python3 implementation of the approach
import math
# Node structure of the tree
class node :
def __init__(self):
self.data = 0
self.left = None
self.right = None
# To create a new node
def newNode(data):
node_ = node()
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
self.isPerfect = None
# To store if sub-tree is complete or not
self.isComplete = None
# size of the tree
self.size = 0
# Root of biggest complete sub-tree
self.rootTree = None
# helper function that returns height
# of the tree given size
def getHeight(size):
return int(math.ceil(math.log(size + 1)/math.log(2)))
# Function to return the biggest
# complete binary sub-tree
def findCompleteBinaryTree(root) :
# Declaring returnType that
# needs to be returned
rt = returnType()
# If root is None then it is considered as both
# perfect and complete binary tree of size 0
if (root == None):
rt.isPerfect = True
rt.isComplete = True
rt.size = 0
rt.rootTree = None
return rt
# Recursive call for left and right child
lv = findCompleteBinaryTree(root.left)
rv = findCompleteBinaryTree(root.right)
# CASE - A
# If left sub-tree is perfect and right is complete and
# there height is also same then sub-tree root
# is also complete binary sub-tree with size equal to
# sum of left and right subtrees plus one for current root
if (lv.isPerfect == True and rv.isComplete == True
and getHeight(lv.size) == getHeight(rv.size)) :
rt.isComplete = True
# If right sub-tree is perfect then
# root is also perfect
rt.isPerfect = rv.isPerfect
rt.size = lv.size + rv.size + 1
rt.rootTree = root
return rt
# CASE - B
# If left sub-tree is complete and right is perfect and the
# height of left is greater than right by one then sub-tree root
# is complete binary sub-tree with size equal to
# sum of left and right subtrees plus one for current root.
# But sub-tree cannot be perfect binary sub-tree.
if (lv.isComplete == True and rv.isPerfect == True
and getHeight(lv.size) == getHeight(rv.size) + 1):
rt.isComplete = True
rt.isPerfect = False
rt.size = lv.size + rv.size + 1
rt.rootTree = root
return rt
# CASE - C
# Else this sub-tree cannot be a complete binary tree
# and simply return the biggest sized complete sub-tree
# found till now in the left or right sub-trees
rt.isPerfect = False
rt.isComplete = False
rt.size =max(lv.size, rv.size)
if(lv.size > rv.size ):
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 the tree
root = newNode(50)
root.left = newNode(30)
root.right = newNode(60)
root.left.left = newNode(5)
root.left.right = newNode(20)
root.right.left = newNode(45)
root.right.right = newNode(70)
root.right.left.left = newNode(10)
# Get the biggest sized complete binary sub-tree
ans = findCompleteBinaryTree(root)
print( "Size : " , ans.size )
# Print the inorder traversal of the found sub-tree
print("Inorder Traversal : ")
inorderPrint(ans.rootTree)
# This code is contributed by Arnab Kundu
C#
// C# implementation of the above 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 Boolean isPerfect;
// To store if sub-tree is complete or not
public Boolean isComplete;
// size of the tree
public int size;
// Root of biggest complete sub-tree
public node rootTree;
};
// helper function that returns height
// of the tree given size
static int getHeight(int size)
{
return (int)Math.Ceiling(Math.Log(size + 1) /
Math.Log(2));
}
// Function to return the biggest
// complete binary sub-tree
static returnType findCompleteBinaryTree(node root)
{
// Declaring returnType that
// needs to be returned
returnType rt=new returnType();
// If root is null then it is considered
// as both perfect and complete binary
// tree of size 0
if (root == null)
{
rt.isPerfect = true;
rt.isComplete = true;
rt.size = 0;
rt.rootTree = null;
return rt;
}
// Recursive call for left and right child
returnType lv = findCompleteBinaryTree(root.left);
returnType rv = findCompleteBinaryTree(root.right);
// CASE - A
// If left sub-tree is perfect and right is
// complete and there height is also same
// then sub-tree root is also complete binary
// sub-tree with size equal to sum of left
// and right subtrees plus one for current root
if (lv.isPerfect == true &&
rv.isComplete == true &&
getHeight(lv.size) == getHeight(rv.size))
{
rt.isComplete = true;
// If right sub-tree is perfect then
// root is also perfect
rt.isPerfect = (rv.isPerfect ? true : false);
rt.size = lv.size + rv.size + 1;
rt.rootTree = root;
return rt;
}
// CASE - B
// If left sub-tree is complete and right is
// perfect and the height of left is greater than
// right by one then sub-tree root is complete
// binary sub-tree with size equal to
// sum of left and right subtrees plus one
// for current root. But sub-tree cannot be
// perfect binary sub-tree.
if (lv.isComplete == true &&
rv.isPerfect == true &&
getHeight(lv.size) == getHeight(rv.size) + 1)
{
rt.isComplete = true;
rt.isPerfect = false;
rt.size = lv.size + rv.size + 1;
rt.rootTree = root;
return rt;
}
// CASE - C
// Else this sub-tree cannot be a complete
// binary tree and simply return the biggest
// sized complete sub-tree found till now
// in the left or right sub-trees
rt.isPerfect = false;
rt.isComplete = false;
rt.size = Math.Max(lv.size, rv.size);
rt.rootTree = (lv.size > rv.size ?
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 the tree
node root = newNode(50);
root.left = newNode(30);
root.right = newNode(60);
root.left.left = newNode(5);
root.left.right = newNode(20);
root.right.left = newNode(45);
root.right.right = newNode(70);
root.right.left.left = newNode(10);
// Get the biggest sized complete binary sub-tree
returnType ans = findCompleteBinaryTree(root);
Console.WriteLine("Size : " + ans.size);
// Print the inorder traversal
// of the found sub-tree
Console.Write("Inorder Traversal : ");
inorderPrint(ans.rootTree);
}
}
// This code is contributed by PrinciRaj1992
Javascript
输出:
Size : 4
Inorder Traversal : 10 45 60 70