题目描述
题目链接:leetcode 106. 从中序与后序遍历序列构造二叉树
根据一棵树的中序遍历与后序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3 / \ 9 20 / \ 15 7
由中序与后序遍历序列构造二叉树
给定如下二叉树:
中序遍历(左根右):ACBDFHEMG
后序遍历(左右根):ABDCHMGEF
由中序与后序遍历序列构造二叉树的步骤:
1.在后序中找到最后一个字母F,F必为二叉树的根。在中序中找到F:ACBDFHEMG。中序遍历中F左边的字母ACBD必在F的左子树上,中序遍历中F右边的字母HEMG必在F的左子树上。如下图所示:
F将中序划分为左边4个字母和右边4个字母,故在后序中把F删掉得到序列ABDCHMGE,再把此序列分为前4个(ABDC)和后4个(HMGE)。如下图所示:
2.可以看到,问题又变成了两个子问题:
(1)由中序遍历ACBD和后序遍历ABDC求左子树。
(2)由中序遍历HEMG和后序遍历HMGE求右子树。
故只需获得解决整体问题的方法,再递归求解子问题即可—分治的思想。
C++代码
/**
* 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 {
public:
/*
dfs参数说明:
l:定位前序的起始位置
r:定位前序的终止位置
last:定位后序的末尾
*/
TreeNode* dfs(vector<int>& inorder, vector<int>& postorder,int l,int r,int last){
TreeNode *root=NULL;
for(int i=l;i<=r;i++)
{
if(inorder[i]==postorder[last]) //找到后序的最后一个节点
{
root=new TreeNode();
root->val=inorder[i]; //令后序的最后一个节点为当前子树的根
//递归构造左右子树,其中对左右子树“last”的更新可以对照中后序确定
root->left=dfs(inorder,postorder,l,i-1,last-(r-i+1));
root->right=dfs(inorder,postorder,i+1,r,last-1);
break;
}
}
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
int l=0,r=inorder.size()-1,last=postorder.size()-1;
return dfs(inorder,postorder,l,r,last);
}
};