leetcode 105 从前序与中序遍历序列构造二叉树

image

前序遍历 + 中序遍历 = 可复原树
后序遍历 + 中序遍历 = 可复原树
前序遍历 + 后序遍历 = 不可

分析:

前序遍历第一个值即为根节点,但是无法知道左子树有几个节点,也就确定不了左右子树

中序遍历如果能知道根节点,就能知道左子树、右子树各自节点数。

组合两者,由前序得到根节点,再由中序判别左、右子树个数。

设前序数组的左边界为pre_left,右边界为pre_right
中序数组的左边界为ino_left,右边界为ino_right

那么根节点pre_root就为 preoder[pre_left]
在inorder数组中找到preoder[pre_left]这个值,假设它的index为 ino_root
那么左子树个数size_left_subtree为 ino_root-ino_left

其中在inorder数组中找到preoder[pre_left],可以进行优化,预先遍历一次preoder,将里面的值存到unorder_map中当作Key,将它的index设为val。后续查找的时候直接取即可。


这样一来:
左子树:
在preorder中的下标范围为[pre_root+1,pre_root+size_left_subtree]
在inorder中的下标范围为[ino_left,ino_root-1]
右子树:
在preoder中的下标范围为[pre_root+size_left_subtree+1,pre_right]
在inorder中的下标范围为[ino_root+1,ino_right]

很明显,每做一次可以将当前节点创建,然后拆分成左子树、右子树,对于两者分别看成根节点,带入各自范围再进行递归,就可以构造整颗树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    unordered_map<int,int> index;
    TreeNode* buildHelper(vector<int>& preorder, vector<int>& inorder,int pre_left,int pre_right,int ino_left,int ino_right)
    {
        if(pre_left>pre_right||ino_left>ino_right) return nullptr;

        int pre_root = pre_left;

        int ino_root = index[preorder[pre_root]];

        TreeNode* node = new TreeNode(preorder[pre_root]);

        int size_left_subtree = ino_root-ino_left;
        node->left = buildHelper(preorder,inorder,pre_left+1,pre_left+size_left_subtree,ino_left,ino_root-1);
        node->right = buildHelper(preorder,inorder,pre_left+size_left_subtree+1,pre_right,ino_root+1,ino_right);
        return node;
    }
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        for(int i = 0; i < n; ++i)
        {
            index[inorder[i]] = i;
        }
        return buildHelper(preorder,inorder,0,n-1,0,n-1);
    }
};
posted @ 2021-04-14 15:11  抚琴思伯牙  阅读(130)  评论(0编辑  收藏  举报