📜  从中序和水平顺序遍历构造一棵树 | 2套

📅  最后修改于: 2021-10-27 08:51:25             🧑  作者: Mango

给定二叉树的中序和层序遍历,构造二叉树。下面是一个例子来说明这个问题。
例子:

Input: Two arrays that represent Inorder
       and level order traversals of a 
       Binary Tree
in[]    = {4, 8, 10, 12, 14, 20, 22};
level[] = {20, 8, 22, 4, 12, 10, 14};

Output: Construct the tree represented 
        by the two arrays.
        For the above two arrays, the 
        constructed tree is shown.

我们在下面的帖子中讨论了一个解决方案,该解决方案适用于 O(N^3)
从中序和水平顺序遍历构造一棵树 |设置 1
方法:以下算法使用O(N^2)时间复杂度解决上述问题,使用c++中的unordered_set数据结构(基本上是做一个hash表)把当前根的左子树的值放在后面,我们会检查以 O(1) 复杂度来查找当前 levelOrder 节点是否是左子树的一部分。
如果它是左子树的一部分,则为左添加一个 lLevel 数组,否则将其添加到右子树的 rLevel 数组中。
下面是上述想法的c++实现

C++
/* program to construct tree using inorder
   and levelorder traversals */
#include 
using namespace std;
 
/* A binary tree node */
struct Node
{
    int key;
    struct Node* left, *right;
};
 
Node* makeNode(int data){
    Node* newNode = new Node();
    newNode->key = data;
    newNode->right = newNode->right = NULL;
    return newNode;
}
 
// Function to build tree from given
// levelorder and inorder
Node* buildTree(int inorder[], int levelOrder[],
                int iStart, int iEnd, int n)
{
    if (n <= 0)
          return NULL;
 
    // First node of level order is root
    Node* root = makeNode(levelOrder[0]);
 
    // Search root in inorder
    int index = -1;
    for (int i=iStart; i<=iEnd; i++){
        if (levelOrder[0] == inorder[i]){
            index = i;
            break;
        }
    }
 
    // Insert all left nodes in hash table
    unordered_set s;
    for (int i=iStart;ileft = buildTree(inorder, lLevel,
                 iStart, index-1, index-iStart);
    root->right = buildTree(inorder, rLevel,
                  index+1, iEnd, iEnd-index);
    return root;
 
}
 
/* Utility function to print inorder
traversal of binary tree */
void printInorder(Node* node)
{
    if (node == NULL)
       return;
    printInorder(node->left);
    cout << node->key << " ";
    printInorder(node->right);
}
 
// Driver Code
int main()
{
    int in[] = {4, 8, 10, 12, 14, 20, 22};
    int level[] = {20, 8, 22, 4, 12, 10, 14};
    int n = sizeof(in)/sizeof(in[0]);
    Node *root = buildTree(in, level, 0,
                           n - 1, n);
 
    /* Let us test the built tree by
     printing Inorder traversal */
    cout << "Inorder traversal of the "
            "constructed tree is \n";
    printInorder(root);
 
    return 0;
}


Java
/*
 * program to construct tree using inorder
 * and levelorder traversals
 */
import java.util.HashSet;
class GFG
{
 
  /* A binary tree node */
  static class Node {
    int key;
    Node left, right;
  };
 
  static Node makeNode(int data) {
    Node newNode = new Node();
    newNode.key = data;
    newNode.right = newNode.right = null;
    return newNode;
  }
 
  // Function to build tree from given
  // levelorder and inorder
  static Node buildTree(int inorder[], int levelOrder[], int iStart, int iEnd, int n) {
    if (n <= 0)
      return null;
 
    // First node of level order is root
    Node root = makeNode(levelOrder[0]);
 
    // Search root in inorder
    int index = -1;
    for (int i = iStart; i <= iEnd; i++) {
      if (levelOrder[0] == inorder[i]) {
        index = i;
        break;
      }
    }
 
    // Insert all left nodes in hash table
    HashSet s = new HashSet<>();
    for (int i = iStart; i < index; i++)
      s.add(inorder[i]);
 
    // Separate level order traversals
    // of left and right subtrees.
    int[] lLevel = new int[s.size()]; // Left
    int[] rLevel = new int[iEnd - iStart - s.size()]; // Right
    int li = 0, ri = 0;
    for (int i = 1; i < n; i++) {
      if (s.contains(levelOrder[i]))
        lLevel[li++] = levelOrder[i];
      else
        rLevel[ri++] = levelOrder[i];
    }
 
    // Recursively build left and right
    // subtrees and return root.
    root.left = buildTree(inorder, lLevel, iStart, index - 1, index - iStart);
    root.right = buildTree(inorder, rLevel, index + 1, iEnd, iEnd - index);
    return root;
 
  }
 
  /*
     * Utility function to print inorder
     * traversal of binary tree
     */
  static void printInorder(Node node) {
    if (node == null)
      return;
    printInorder(node.left);
    System.out.print(node.key + " ");
    printInorder(node.right);
  }
 
  // Driver Code
  public static void main(String[] args) {
 
    int in[] = { 4, 8, 10, 12, 14, 20, 22 };
    int level[] = { 20, 8, 22, 4, 12, 10, 14 };
    int n = in.length;
    Node root = buildTree(in, level, 0, n - 1, n);
 
    /*
         * Let us test the built tree by
         * printing Inorder traversal
         */
    System.out.println("Inorder traversal of the constructed tree is ");
    printInorder(root);
 
  }
}
 
// This code is contributed by sanjeev2552


Javascript


Java
import java.util.HashMap;
 
//class Node
class Node{
    int data;
    Node left,right;
    Node(int data){
        this.data = data;
        left = right = null;
    }
}
 
public class ConstructTree {
     
    //hashmap to store the indices of levelorder array
    HashMap map = new HashMap<>();
     
    //function to construct hashmap
    void constructMap(int level[]) {
        for(int i=0;i end)
            return null;
         
        int min_index = start;
         
        //In the range of start & end from inorder, search the element
        //with least index from level order map
        for(int i=start+1;i<=end;i++) {
            int temp = in[i];
            //if current element from inorder have least index in
            //levelorder map, update min_index
            if(map.get(in[min_index]) > map.get(temp))
                min_index = i;
        }
         
        //create a node with current element
        Node root = new Node(in[min_index]);
         
        //if start is equal to end, then return root
        if(start == end)
            return root;
         
        //construct left and right subtrees
        root.left = construct(in,level,start,min_index-1);
        root.right = construct(in,level,min_index+1,end);
         
        return root;
    }
     
    //function to print inorder
    void printInorder(Node node) {
        if (node == null)
          return;
        printInorder(node.left);
        System.out.print(node.data + " ");
        printInorder(node.right);
      }
     
    //Driver function
    public static void main(String[] args) {
        ConstructTree tree = new ConstructTree();
         
        int in[]    = {4, 8, 10, 12, 14, 20, 22};
        int level[] = {20, 8, 22, 4, 12, 10, 14};
         
        //function calls
        tree.constructMap(level);
        int n = level.length;
        Node root = tree.construct(in, level, 0, n-1);
        tree.printInorder(root);
    }
}
 
//This method is contributed by Likhita AVL


输出
Inorder traversal of the constructed tree is 
4 8 10 12 14 20 22 

时间复杂度:O(N^2)

优化:没有单独的左子树和右子树的级别顺序遍历数组。

方法:使用哈希。

使用HashMap来存储层序遍历的索引。在inorder的start&end范围内,从层序图中搜索索引最少的元素。递归创建左右子树。

index -> the least index
for left subtree: start to index-1
for right subtree: index+1 to end

执行:

Java

import java.util.HashMap;
 
//class Node
class Node{
    int data;
    Node left,right;
    Node(int data){
        this.data = data;
        left = right = null;
    }
}
 
public class ConstructTree {
     
    //hashmap to store the indices of levelorder array
    HashMap map = new HashMap<>();
     
    //function to construct hashmap
    void constructMap(int level[]) {
        for(int i=0;i end)
            return null;
         
        int min_index = start;
         
        //In the range of start & end from inorder, search the element
        //with least index from level order map
        for(int i=start+1;i<=end;i++) {
            int temp = in[i];
            //if current element from inorder have least index in
            //levelorder map, update min_index
            if(map.get(in[min_index]) > map.get(temp))
                min_index = i;
        }
         
        //create a node with current element
        Node root = new Node(in[min_index]);
         
        //if start is equal to end, then return root
        if(start == end)
            return root;
         
        //construct left and right subtrees
        root.left = construct(in,level,start,min_index-1);
        root.right = construct(in,level,min_index+1,end);
         
        return root;
    }
     
    //function to print inorder
    void printInorder(Node node) {
        if (node == null)
          return;
        printInorder(node.left);
        System.out.print(node.data + " ");
        printInorder(node.right);
      }
     
    //Driver function
    public static void main(String[] args) {
        ConstructTree tree = new ConstructTree();
         
        int in[]    = {4, 8, 10, 12, 14, 20, 22};
        int level[] = {20, 8, 22, 4, 12, 10, 14};
         
        //function calls
        tree.constructMap(level);
        int n = level.length;
        Node root = tree.construct(in, level, 0, n-1);
        tree.printInorder(root);
    }
}
 
//This method is contributed by Likhita AVL
输出
4 8 10 12 14 20 22 

时间复杂度: O(n^2)。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程