从前序遍历构造完美二叉树
给定一个数组pre[] ,表示由N个节点组成的完美二叉树的前序遍历,任务是从给定的前序遍历构造一个完美二叉树并返回树的根。
例子:
Input: pre[] = {1, 2, 4, 5, 3, 6, 7}
Output:
1
/ \
/ \
2 3
/ \ / \
/ \ / \
4 5 6 7
Input: pre[] = {1, 2, 3}
Output:
1
/ \
/ \
2 3
一般要构造二叉树,只用前序遍历是做不到的,但这里给出了一个额外的条件,即二叉树是完美二叉树。我们可以使用那个额外的条件。
对于完美二叉树,每个节点都有 2 个或 0 个子节点,并且所有叶节点都存在于同一级别。二叉树的前序遍历首先包含根,然后是左子树的前序遍历,然后是右子树的前序遍历。所以对于完美二叉树根应该在两个子树中具有相同数量的子树,因此在前序遍历中根之后的元素数量(例如,n)应该是偶数(2 * 一个子树中的节点数,因为它是完美的二叉树)。并且由于完美二叉树的每个子树的节点数相等,我们可以找到左子树的前序遍历(在整个树的前序遍历中,它是根之后的数组的一半),我们知道前序遍历右子树必须在左子树的前序遍历之后,所以剩下的一半是右子树的前序遍历。
所以前序遍历的第一个元素是根,我们会用这个元素构建一个节点作为根,那么我们可以很容易地找到根的左右子树的前序遍历,然后递归地构建左子树和右子树的前序遍历。根的右子树。
方法:给定的问题可以使用递归来解决。请按照以下步骤解决问题:
- 创建一个函数,比如BuildPerfectBT_helper ,其参数为preStart 、 preEnd 、 pre[]其中preStart表示数组pre[] 的起始索引, preEnd 表示数组 pre[]的结束索引,并执行以下步骤:
- 如果preStart的值大于preEnd ,则返回NULL 。
- 将root初始化为pre[preStart] 。
- 如果preStart的值与preEnd相同,则返回root 。
- 初始化 4 个变量,将 leftPreStart设为preStart + 1 ,将 rightPreStart设为leftPreStart + (preEnd – leftPreStart+1)/2 ,将 leftPreEnd设为rightPreStart – 1 ,将 rightPreEnd设为preEnd 。
- 通过使用参数leftPreStart 、 leftPreEnd和pre[]递归调用函数buildPerfectBT_helper()来修改root->left的值。
- 通过使用参数rightPreStart 、 rightPreEnd和pre[]递归调用函数buildPerfectBT_helper()来修改root->right的值。
- 执行上述步骤后,返回root 。
- 创建完美二叉树后,打印树的中序遍历。
下面是讨论的上述步骤的图示:
Step 1: build([1, 2, 4, 5, 3, 6, 7])
Step 2:
1
/ \
/ \
build([2, 4, 5]) build([3, 6, 7])
Now first element (1 here) is root, then the subarray after the first element ( which is [2,4,5,3,6,7] here ) contains the preorder traversals of the left and right subtrees. And we know left subtree’s preorder traversal is first half , i.e, [2,4,5] , and the right subtree’s preorder traversal is the second half , i.e, [3,6,7]. Now recursively build the left and right subtrees.
Step 3:
1
___________|_________________
/ \
/ \
2 3
______/___________ _______\____________
/ \ / \
/ \ / \
build([4]) build([5]) build([6]) build([7])
Step 4:
1
/ \
/ \
2 3
/ \ / \
/ \ / \
4 5 6 7
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Structure of the tree
struct Node {
int data;
Node *left, *right;
Node(int val)
{
data = val;
left = right = NULL;
}
};
// Function to create a new node with
// the value val
Node* getNewNode(int val)
{
Node* newNode = new Node(val);
newNode->data = val;
newNode->left = newNode->right = NULL;
// Return the newly created node
return newNode;
}
// Function to create the Perfect
// Binary Tree
Node* buildPerfectBT_helper(int preStart,
int preEnd,
int pre[])
{
// If preStart > preEnd return NULL
if (preStart > preEnd)
return NULL;
// Initialize root as pre[preStart]
Node* root = getNewNode(pre[preStart]);
;
// If the only node is left,
// then return node
if (preStart == preEnd)
return root;
// Parameters for further recursion
int leftPreStart = preStart + 1;
int rightPreStart = leftPreStart
+ (preEnd - leftPreStart + 1) / 2;
int leftPreEnd = rightPreStart - 1;
int rightPreEnd = preEnd;
// Recursive Call to build the
// subtree of root node
root->left = buildPerfectBT_helper(
leftPreStart, leftPreEnd, pre);
root->right = buildPerfectBT_helper(
rightPreStart, rightPreEnd, pre);
// Return the created root
return root;
}
// Function to build Perfect Binary Tree
Node* buildPerfectBT(int pre[], int size)
{
return buildPerfectBT_helper(0, size - 1, pre);
}
// Function to print the Inorder of
// the given Tree
void printInorder(Node* root)
{
// Base Case
if (!root)
return;
// Left Recursive Call
printInorder(root->left);
// Print the data
cout << root->data << " ";
// Right Recursive Call
printInorder(root->right);
}
// Driver Code
int main()
{
int pre[] = { 1, 2, 4, 5, 3, 6, 7 };
int N = sizeof(pre) / sizeof(pre[0]);
// Function Call
Node* root = buildPerfectBT(pre, N);
// Print Inorder Traversal
cout << "\nInorder traversal of the tree: ";
printInorder(root);
return 0;
}
Java
// Java program for the above approach
public class Main
{
// Structure of the tree
static class Node {
public int data;
public Node left, right;
public Node(int val)
{
data = val;
left = right = null;
}
}
// Function to create a new node with
// the value val
static Node getNewNode(int val)
{
Node newNode = new Node(val);
// Return the newly created node
return newNode;
}
// Function to create the Perfect
// Binary Tree
static Node buildPerfectBT_helper(int preStart, int preEnd, int[] pre)
{
// If preStart > preEnd return NULL
if (preStart > preEnd)
return null;
// Initialize root as pre[preStart]
Node root = getNewNode(pre[preStart]);
// If the only node is left,
// then return node
if (preStart == preEnd)
return root;
// Parameters for further recursion
int leftPreStart = preStart + 1;
int rightPreStart = leftPreStart + (preEnd - leftPreStart + 1) / 2;
int leftPreEnd = rightPreStart - 1;
int rightPreEnd = preEnd;
// Recursive Call to build the
// subtree of root node
root.left = buildPerfectBT_helper(
leftPreStart, leftPreEnd, pre);
root.right = buildPerfectBT_helper(
rightPreStart, rightPreEnd, pre);
// Return the created root
return root;
}
// Function to build Perfect Binary Tree
static Node buildPerfectBT(int[] pre, int size)
{
return buildPerfectBT_helper(0, size - 1, pre);
}
// Function to print the Inorder of
// the given Tree
static void printInorder(Node root)
{
// Base Case
if (root == null)
return;
// Left Recursive Call
printInorder(root.left);
// Print the data
System.out.print(root.data + " ");
// Right Recursive Call
printInorder(root.right);
}
public static void main(String[] args) {
int[] pre = { 1, 2, 4, 5, 3, 6, 7 };
int N = pre.length;
// Function Call
Node root = buildPerfectBT(pre, N);
// Print Inorder Traversal
System.out.print("Inorder traversal of the tree: ");
printInorder(root);
}
}
// This code is contributed by suresh07.
Python3
# Python3 program for the above approach
# Structure of the tree
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
# Function to create a new node with
# the value val
def getNewNode(val):
newNode = Node(val)
# Return the newly created node
return newNode
# Function to create the Perfect
# Binary Tree
def buildPerfectBT_helper(preStart, preEnd, pre):
# If preStart > preEnd return NULL
if (preStart > preEnd):
return None
# Initialize root as pre[preStart]
root = getNewNode(pre[preStart])
# If the only node is left,
# then return node
if (preStart == preEnd):
return root
# Parameters for further recursion
leftPreStart = preStart + 1
rightPreStart = leftPreStart + int((preEnd - leftPreStart + 1) / 2)
leftPreEnd = rightPreStart - 1
rightPreEnd = preEnd
# Recursive Call to build the
# subtree of root node
root.left = buildPerfectBT_helper(leftPreStart, leftPreEnd, pre)
root.right = buildPerfectBT_helper(rightPreStart, rightPreEnd, pre)
# Return the created root
return root
# Function to build Perfect Binary Tree
def buildPerfectBT(pre, size):
return buildPerfectBT_helper(0, size - 1, pre)
# Function to print the Inorder of
# the given Tree
def printInorder(root):
# Base Case
if (root == None):
return
# Left Recursive Call
printInorder(root.left)
# Print the data
print(root.data, "", end = "")
# Right Recursive Call
printInorder(root.right)
pre = [ 1, 2, 4, 5, 3, 6, 7 ]
N = len(pre)
# Function Call
root = buildPerfectBT(pre, N)
# Print Inorder Traversal
print("Inorder traversal of the tree: ", end = "")
printInorder(root)
# This code is contributed by decode2207.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG {
// Structure of the tree
class Node {
public int data;
public Node left, right;
public Node(int val)
{
data = val;
left = right = null;
}
}
// Function to create a new node with
// the value val
static Node getNewNode(int val)
{
Node newNode = new Node(val);
// Return the newly created node
return newNode;
}
// Function to create the Perfect
// Binary Tree
static Node buildPerfectBT_helper(int preStart, int preEnd, int[] pre)
{
// If preStart > preEnd return NULL
if (preStart > preEnd)
return null;
// Initialize root as pre[preStart]
Node root = getNewNode(pre[preStart]);
// If the only node is left,
// then return node
if (preStart == preEnd)
return root;
// Parameters for further recursion
int leftPreStart = preStart + 1;
int rightPreStart = leftPreStart + (preEnd - leftPreStart + 1) / 2;
int leftPreEnd = rightPreStart - 1;
int rightPreEnd = preEnd;
// Recursive Call to build the
// subtree of root node
root.left = buildPerfectBT_helper(
leftPreStart, leftPreEnd, pre);
root.right = buildPerfectBT_helper(
rightPreStart, rightPreEnd, pre);
// Return the created root
return root;
}
// Function to build Perfect Binary Tree
static Node buildPerfectBT(int[] pre, int size)
{
return buildPerfectBT_helper(0, size - 1, pre);
}
// Function to print the Inorder of
// the given Tree
static void printInorder(Node root)
{
// Base Case
if (root == null)
return;
// Left Recursive Call
printInorder(root.left);
// Print the data
Console.Write(root.data + " ");
// Right Recursive Call
printInorder(root.right);
}
static void Main() {
int[] pre = { 1, 2, 4, 5, 3, 6, 7 };
int N = pre.Length;
// Function Call
Node root = buildPerfectBT(pre, N);
// Print Inorder Traversal
Console.Write("Inorder traversal of the tree: ");
printInorder(root);
}
}
// This code is contributed by mukesh07.
Javascript
Inorder traversal of the tree: 4 2 5 1 6 3 7
时间复杂度: O(N)
辅助空间: O(N)