重建二叉树

 题目:

输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树

二叉树中每个节点的值都互不相同;

输入的前序遍历和中序遍历一定合法;

 

题目分析:

前序遍历是先访问根节点,再访问左子树,最后访问右子树

中序遍历是先访问左子树,再访问根节点,最后访问右子树

我们首先取出前序遍历序列的第一个元素,在中序遍历序列中找到这一个元素,此时在中序遍历序列中该元素的左侧为该元素的左子树,右侧为该元素的右子树

假设左子树的长度为k,则在前序遍历中该元素的后k个元素为该元素的左子素

同理,假设右子树的长度为m,则在前序遍历中左子树末尾元素的的后m个元素为该元素的右子树

 

 解决方案:

 根据这一特性,我们使用递归,首先找出子树根结点的位置

然后,我们继续遍历左右子树,左右子树的在前序遍历序列和中序遍历序列下标边界需要特别注意

 

如何确定左右子树的下标边界?

假设此时子树的前序遍历序列和中序遍历序列的边界为[pl, pr], [il, ir],根结点的下标为k

该子树的左子树

前序遍历序列的左边界(pl')  = 左边界(pl) + 1

前序遍历序列的右边界下标(pr’)  = 左边界的下标(pl + 1) + 左子树长度(length) - 1

左子树长度(length) = 根结点的下标位置(k) - 中序遍历的左边界(ir)

左子树中序遍历的左边界(il') = 中序遍历的左边界的下标(il)

左子树中序遍历的右边界(ir') = 根结点下标(k)  - 1

 

子树的右子树

前序遍历序列的左边界(pl')  = 前序遍历序列的右边界下标(pr' ) + 1

前序遍历序列的右边界(pr') =  前序遍历序列的右边界(pr)

右子树中序遍历的左边界(il') =  根结点的下标位置(k) + 1

右子树中序遍历的右边界(ir') = 右子树中序遍历的右边界(ir

 

以下树为例:

第一次递归操作:[pl, pr, il, ir] = [0, 7, 0, 7]

前序遍历序列

 中序遍历序列

第二次递归操作:[pl, pr, il, ir] = [1, 3, 0, 2]

前序遍历序列

 

中序遍历序列

 

 

代码:

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     vector<int> preorder;
13     vector<int> inorder;
14     map<int, int> hash;
15     TreeNode* buildTree(vector<int>& _preorder, vector<int>& _inorder) {
16         preorder = _preorder;
17         inorder = _inorder;
18         for(int i = 0; i < inorder.size(); i++) hash[inorder[i]] = i;
19         return dfs(0, preorder.size()-1, 0, inorder.size()-1);
20     }
21     TreeNode* dfs(int pl, int pr, int il, int ir)
22     {
23         if(pl > pr) return nullptr;
24         int k = hash[preorder[pl]];
25         auto root = new TreeNode(preorder[pl]);
26         auto left = dfs(pl + 1, pl + 1 + k -il -1, il, k - 1); //前序遍历左边界+1,左边界+左子树长度,中序遍历左边界,根元素位置-1
27         auto right = dfs(pl + k - il +1, pr, k + 1, ir); //左子树+1,前序遍历右边界,根元素位置+1,中序遍历右边界
28         root->left = left;
29         root->right = right;
30         return root;
31     }
32 };

 

posted @ 2019-05-31 03:02  roov  阅读(5)  评论(0编辑  收藏  举报