题目链接:
1.链接: 105. 从前序与中序遍历序列构造二叉树.
2.链接: 106. 从中序与后序遍历序列构造二叉树.
3.链接: 889. 根据前序和后序遍历构造二叉树.
这三道题都可以用递归和迭代来解决,这次就贴三道题的递归解法,都是一个解题思路:先根据给定遍历的特点找到根结点的位置(前序:根-左-右,中序:左-根-右,后序:左-右-根),找到根结点以后(创建根节点),再根据另外一个给定遍历来确定左右子树的结点数,再递归创建左右子树即可。
题外话:对于这种二叉树的题目,通常用到递归都是类似的模板:
递归截止条件;
root->left = function();
root->right = function();
为更容易理解,以105题为例做一个描述:我们的目的(函数)是通过给定信息创建一个二叉树,对前序遍历和中序遍历来说,它的结构为:
我用pl,pr表示前序遍历序列中首尾两个数的位置,il,ir表示中序遍历序列中守尾两个数的位置,pos表示前序遍历序列中首元素在中序遍历序列中的位置即根在中序遍历序列中的位置,找pos的目的是:通过
中序遍历来确定树的左右子树的结点数量。确定树的左右子树中结点的数量后,我们只需要在前序遍历序列中找到对应的左子树及右子树的范围即可,接下来就是对左右子树进行递归创建。
105题代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
unordered_map<int,int> mp;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i =0;i!=preorder.size();++i)
mp[inorder[i]] = i;
return creat(preorder,0,preorder.size()-1, inorder,0,inorder.size()-1);
}
TreeNode* creat(vector<int>& preorder,int pl,int pr, vector<int>& inorder,int il,int ir)
{
if(pl>pr || il>ir) return NULL;
int pos = mp[preorder[pl]];
TreeNode* root = new TreeNode(preorder[pl]);
root->left = creat(preorder,pl+1,pos+pl-il,inorder,il,pos-1);
root->right = creat(preorder,pos+pl-il+1,pr,inorder, pos+1,ir);
return root;
}
};
后面两题的道理类似。但从前序及后续遍历序列创建二叉树中思路有细微差别,因为只有中序遍历是通过找到根节点后就能自然将序列分成左右两部分,而前后序遍历的序列没有这一特点。
那依据前序和后序遍历序列怎么创建二叉树呢?
我们可以假设左子树的长度为L,利用后续遍历序列的特点:左-右-根,那么后序遍历序列块的最开始长度为L的部分为为左子树的结点,而前序遍历序列的首元素为根结点,以pre,post分别表示前序和后序遍历的序列,则有:pre[1] = post[L-1];这样即可确定各子树结点在各序列中的位置,后续按照同样的递归方法即可创建二叉树。
889题代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
unordered_map<int,int> mp;
TreeNode* constructFromPrePost(vector<int>& pre, vector<int>& post) {
for(int i =0;i<pre.size();i++) mp[post[i]] = i;
return creat(pre,0,pre.size()-1,post,0,post.size()-1);
}
TreeNode* creat(vector<int>& pre,int prl,int prr, vector<int>& post,int pl,int pr)
{
if(pl>pr) return NULL;
TreeNode* root = new TreeNode(pre[prl]);
if(prl+1>prr) return root;
int lpos = mp[pre[prl+1]];
root->left = creat(pre,prl+1,lpos-pl+prl+1,post,pl,lpos);
root->right = creat(pre,lpos-pl+prl+2,prr,post,lpos+1,pr-1);
return root;
}
};
106题代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
unordered_map<int,int> mt;
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.empty()) return NULL;
for(int i = 0;i<inorder.size();++i)
{
mt[inorder[i]] = i;
}
return findroot(inorder,0,inorder.size()-1,postorder,0,postorder.size()-1);
}
TreeNode* findroot(vector<int>& inorder,int il,int ir, vector<int>& postorder,int pl,int pr)
{
if(il>ir||pl>pr) return NULL;
TreeNode *T = new TreeNode(postorder[pr]);
int pos = mt[postorder[pr]];
T->left=findroot(inorder,il,pos-1,postorder,pl,pos-1-il+pl);
T->right=findroot(inorder,pos+1,ir,postorder,pos-il+pl,pr-1);
return T;
}
};
最后!!!!注意889题中递归的截止条件也会有细微差别。
第一次写博客,没想到速度还挺快哈哈哈!!