Leetcode|二叉树的修改与构造|从前中|后中|前后遍历序列构造二叉树


在这里插入图片描述

一、前序+中序

1.1 递归(哈希表优化)

class Solution {
private:
    unordered_map<int, int> val2idx;
    int preIdx = 0;
public:
    TreeNode* traverse(vector<int>& preorder, vector<int>& inorder, int left, int right) {
        if (left > right) return nullptr;
        auto root = new TreeNode(preorder[preIdx]);      
        int mid = val2idx[ preorder[preIdx++] ];
        root->left = traverse(preorder, inorder, left, mid - 1);
        root->right = traverse(preorder, inorder, mid + 1, right);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int index = 0;
        for (auto& val : inorder) val2idx[val] = index++;
        return traverse(preorder, inorder, 0, preorder.size() - 1);
    }
};

二、后序+中序

2.1 递归(未优化)

class Solution {
public:
    TreeNode* traverse(vector<int>& inorder, vector<int>& postorder, int left, int right) {
        if (left > right) return nullptr;
        auto root = new TreeNode(postorder.back());
        int rootIndex;
        for (int i=left;i <= right;i++)
            if (inorder[i] == postorder.back()) {
                rootIndex = i;
                break;
            }
        postorder.pop_back();
        root->right = traverse(inorder, postorder, rootIndex + 1, right);
        root->left = traverse(inorder, postorder, left, rootIndex - 1);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return traverse(inorder, postorder, 0, inorder.size() - 1);
    }
};

由于每次要重新在inorder中从left到right顺序搜索与根节点相同值的索引,因此,对于海量数据的中序inorder向量,查值效率不是最高。
在这里插入图片描述

2.2 递归(哈希表优化)

对于海量数据的中序向量inorder,每次从left到right一个个检索与后序最后一个值是否相同,效率有些低。为了加速检索,可以空间换时间,即引入加速检索的哈希表数据结构,具体代码如下

class Solution {
private:
    unordered_map<int, int> val2idx;  // 存储中序数组的哈希表
    int postIdx = 0;
public:
    TreeNode* traverse(vector<int>& inorder, vector<int>& postorder, int left, int right) {
        if (left > right) return nullptr;
        auto root = new TreeNode( postorder[postIdx] );
        // 通过哈希表快速获取根节点在中序inorder中的索引
        int mid = val2idx[ postorder[postIdx--] ];
        root->right = traverse(inorder, postorder, mid + 1, right);
        root->left = traverse(inorder, postorder, left, mid - 1);
        return root;
    }

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int index = 0;
        // 注意:后序的根节点一定是从后往前
        postIdx = inorder.size() - 1;
        // 将中序数组按<val, index>存储到哈希表中
        for (auto& val : inorder) val2idx[val] = index++;
        return traverse(inorder, postorder, 0, inorder.size() - 1);
    }
};

在这里插入图片描述

三、前序+后序

在这里插入图片描述

在这里插入图片描述
【思路】:不同于前中和后中,前后先通过前序最左节点,找到根节点,而前序根节点的右邻居是根节点的左子树,只是不知道左子树区间是多少,因此需要根据根节点左子树定位后序中的相同左子根节点,这样后序中根节点的左侧即为左子树区间,右侧至尾节点左邻居为右子树

  • pre左子树区间:[preleft + 1, preleft + 1 + mid - postleft]
  • pre右子树区间:[postleft, mid]
  • post左子树区间:[preleft + 2 + mid - postleft, preright]
  • post右子树区间:[mid + 1, postright - 1]

3.1 递归(哈希表优化)

class Solution {
private:
    unordered_map<int, int> val2idx;
public:
    TreeNode* traverse(vector<int>& pre, vector<int>& post, int preleft, int preright, int postleft, int postright) {
        if (preleft > preright || postleft > postright) return nullptr;
        auto root = new TreeNode(pre[preleft]);
        if (preleft == preright) return root;
        int mid = val2idx[ pre[preleft + 1] ];
        // pre左子树区间:[preleft + 1, preleft + 1 + mid - postleft]
        // pre右子树区间:[postleft, mid]
        // post左子树区间:[preleft + 2 + mid - postleft, preright]
        // post右子树区间:[mid + 1, postright - 1]
        root->left = traverse(pre, post, preleft + 1, preleft + 1 + mid - postleft, postleft, mid);
        root->right = traverse(pre, post, preleft + 2 + mid - postleft, preright, mid + 1, postright - 1);
        return root;
    }

    TreeNode* constructFromPrePost(vector<int>& pre, vector<int>& post) {
        int index = 0;
        for (auto& val : post) val2idx[val] = index++;
        return traverse(pre, post, 0, pre.size() - 1, 0, post.size() - 1);
    }
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SL_World

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值