105-LeetCode 根据前序+ 中序序列构造二叉树

文章目录

    • 题目
    • 法一:递归


题目

从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。

注意:你可以假设树中没有重复的元素。

例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:
3
/ \
9 20
/
15 7




法一:递归

思路
根据前序遍历可以知道根节点,根据根节点可以在中序序列中得到左子树 和 右子树 的中序序列
我们可以得到如下信息:

  • 先序序列------根节点的值
  • 中序序列------根节点所在的下标
  • 中序序列-----左子树的长度
  • 中序序列-----右子树的长度
    105-LeetCode 根据前序+ 中序序列构造二叉树_第1张图片

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

struct TreeNode
{
    int data;
    TreeNode * left;
    TreeNode * right;
    TreeNode(int value)
    {
        data = value;
        left = NULL;
        right = NULL;
    }
};


// 层序输出构建的二叉树
void PrintFromTopToBottom(TreeNode * root)
{
    if(root == NULL)
    {
        return;
    }

    list<TreeNode *> l;
    l.push_back(root);

    while(!l.empty())
    {
        TreeNode * temp = l.front();
        cout << temp->data << " ";
        l.pop_front();

        if(temp->left)
        {
            l.push_back(temp->left);
        }
        if(temp->right)
        {
            l.push_back(temp->right);
        }
    }
    cout << endl;
}


map<int , int> index;           // 存储中序遍历----数据 vs 下标


// 递归 
// 根据前序遍历可以知道根节点,根据根节点可以在中序序列中得到左子树 和 右子树 的中序序列
TreeNode * MyBuildTree(const vector<int> & preorder , const vector<int> & inorder , int preOrder_left , int preOrder_right , int inOrder_left , int inOrder_right)
{
    int size = preorder.size();
    // 可根据数据去知道下标
    for(int i = 0; i < size;++i)
    {
        index[inorder[i]] = i;
    }

    if(preOrder_left > preOrder_right)
    {
        return NULL;
    }

    // 先序遍历中根节点的下标
    int preOrder_root = preOrder_left;

    // 根节点的值
    int root_value = preorder[preOrder_root];
    TreeNode * root = new TreeNode(root_value);

    // 中序遍历中根节点的下标
    int inOrder_root = index[root_value];
    // 得到左子树的节点数目
    int size_left_subtree = inOrder_root - inOrder_left;

    // 先序遍历下标       根                          左                              右
    // 先序遍历     preOrder_left       preOrder_left + size_left_subtree       preOrder_right
    // 中序遍历下标       左                          根                              右
    // 中序遍历     inOrder_left                inOrder_root                    inOrder_right

    // 递归构造左子树,并连接到左节点
    root->left = MyBuildTree(preorder , inorder , preOrder_left + 1 , preOrder_left + size_left_subtree , inOrder_left , inOrder_root - 1);
    // 递归构造右子树,并连接到右节点
    root->right = MyBuildTree(preorder , inorder , preOrder_left + size_left_subtree + 1 , preOrder_right , inOrder_root + 1 , inOrder_right);

    return root;
}


// 递归
TreeNode * BuildTree(const vector<int> & preorder ,const vector<int> & inorder)
{
    if(preorder.empty())
    {
        return NULL;
    }

    int size = preorder.size();

    // 可根据数据去知道下标
    for(int i = 0; i < size;++i)
    {
        index[inorder[i]] = i;
    }
    
    return MyBuildTree(preorder , inorder , 0 , size - 1 , 0 , size -1);
}

int main()
{
    vector<int> preOrder;
    preOrder.push_back(8);
    preOrder.push_back(4);
    preOrder.push_back(9);
    preOrder.push_back(12);
    preOrder.push_back(2);
    preOrder.push_back(1);
    preOrder.push_back(5);
    
    vector<int> inOrder;
    inOrder.push_back(9);
    inOrder.push_back(4);
    inOrder.push_back(12);
    inOrder.push_back(8);
    inOrder.push_back(1);
    inOrder.push_back(2);
    inOrder.push_back(5);

    TreeNode * root = BuildTree(preOrder , inOrder);
    PrintFromTopToBottom(root);

    return 0;
}

采用层序遍历输出我们构建的二叉树,输出结果如下:

8 4 2 9 12 1 5

你可能感兴趣的:(LeetCode)