C++利用前序序列和中序序列构建二叉树

重建二叉树

在数据结构这门课中很容易碰见这个问题,感觉手写的话很容易写出来,但是没有用代码实现过,这里记录一下如何用代码实现。
在这里插入图片描述
思路:
思路:利用前序中序遍历的性质,首先在前序中找到根节点,那么在中序遍历中,根节点的左边一定是他的左子树,右边是右子树,然后根据这个特点,对左和右子树继续进行分治。最后就可以得到返回结点,这里的核心方法肯定还是递归。
因为这个题不会重复,利用一下hashMap
在中序遍历中对根节点进行定位时,一种简单的方法是直接扫描整个中序遍历的结果并找出根节点,但这样做的时间复杂度较高。我们可以考虑使用哈希表来帮助我们快速地定位根节点。对于哈希映射中的每个键值对,键表示一个元素(节点的值),值表示其在中序遍历中的出现位置。在构造二叉树的过程之前,我们可以对中序遍历的列表进行一遍扫描,就可以构造出这个哈希映射。在此后构造二叉树的过程中,我们就只需要 O(1) 的时间对根节点进行定位了。

struct TreeNode {
    
    
      int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode(int x) : val(x), left(NULL), right(NULL) {
    
    }
 };
class Solution {
    
    
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    
    
        this->preorder = preorder;
        // 利用hashMap映射索引,可以在每一次取的时候时间复杂度为o(1)
        for(int i = 0; i < inorder.size(); i++) {
    
    
             dic[inorder[i]] = i;
        }
        return recur(0, 0, inorder.size() - 1);
    }
    // 全局变量,方便在后续递归时使用。
    vector<int> preorder;
    unordered_map<int, int> dic;
    // 通过下面参数锁定遍历划分的范围,含义下面会讲。
    TreeNode* recur(int root, int left, int right) {
    
     
        if(left > right) {
    
     //  已经越过叶子结点.
            return nullptr; 
        }                       
        TreeNode* node = new TreeNode(preorder[root]);          // 建立根节点
        int i = dic[preorder[root]];                            // 获取当前结点在中序的index
        // 三个参数的含意
        // root:是根节点在前序遍历的位置
        // left:在中序遍历中左边界
        // 递归左子树时,左边界限是确定的,i - 1是右边界,因为i是中序的索引,他的左子树的右边界一定在他的上一位。
        node->left = recur(root + 1, left, i - 1);              // 开启左子树递归
        // 递归右子树时,右边界确定,i + 1是左边界,理由同上,这里的root计算实际就是在前序中加上左子树的长度加一找到右子树根结点。
        node->right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归
        return node;                                            // 回溯返回根节点
    }
};



猜你喜欢

转载自blog.csdn.net/chabuduoxs/article/details/125036434
今日推荐