重建二叉树
- 参与人数:1892时间限制:1秒空间限制:32768K
- 通过比例:19.08%
- 最佳记录:0 ms|0K(来自 shi_kai)
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
二叉树,先回顾下二叉树的特点:
关于二叉树;n总=n0+n1+n2;n0=n2 + 1 ;so…n总=n1+2*n2+1
每层的最大结点数2^(n-1); 结点总数最大是2^n - 1
关于遍历:先序是:根左右;
中序是:左根右;
后序是:左右根;
一般我们会选择递归的方法来遍历这样代码回简单些;这题也是一样的。
但由于已经给出了函数的框架,所以代码回收到限制;
思路还是递归,方法是分段递归;
/*
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode *root;*/
class Solution {
public:
struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) {
//判定递归终止条件;
if(pre.size() == 0 || in.size() == 0) {
return NULL;
}
//定义Node节点并其求根节点;
int root = pre[0];
TreeNode* node = new TreeNode(root);
vector<int>::iterator it;
//求左右子树的遍历序列;
vector<int> preLeft, preRight, inLeft, inRight;
//1、求根节点在中序遍历序列中的位置;
vector<int>::iterator i;
for(it = in.begin(); it != in.end(); it++) {
if(root == *it) {
i = it;
}
}
//2、求左右子树的中序遍历子序列;
int k = 0;
for(it = in.begin(); it != in.end(); it++) {
if(k == 0)
inLeft.push_back(*it);
else if(k == 1)
inRight.push_back(*it);
if(it == i)
k = 1;
}
//3、求左右子树的前序遍历子序列;
k = 0;
vector<int>::iterator ite;
for(it = pre.begin()+1; it != pre.end(); it++)
{
for(ite = inLeft.begin(); ite != inLeft.end(); ite++)
{
if(*it == *ite)
{
preLeft.push_back(*it);
k = 1;
}
}
if(k == 0)
{
preRight.push_back(*it);
}
k = 0;
}
//根据遍历序列求出跟的左右节点;
node->left = reConstructBinaryTree(preLeft,inLeft);
node->right = reConstructBinaryTree(preRight,inRight);
//返回节点地址;
return node;
}
};
学会了方法可以在HDUOJ上做一个,练习一下;
题意是:已知先序和中序输出二叉树的后序!
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1710
249ms AC
#include<stdio.h>
#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode *root;
class Solution {
public:
struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) {
//判定递归终止条件;
if(pre.size() == 0 || in.size() == 0) {
return NULL;
}
//定义Node节点并其求根节点;
int root = pre[0];
TreeNode* node = new TreeNode(root);
vector<int>::iterator it;
//求左右子树的遍历序列;
vector<int> preLeft, preRight, inLeft, inRight;
//1、求根节点在中序遍历序列中的位置;
vector<int>::iterator i;
for(it = in.begin(); it != in.end(); it++) {
if(root == *it) {
i = it;
}
}
//2、求左右子树的中序遍历子序列;
int k = 0;
for(it = in.begin(); it != in.end(); it++) {
if(k == 0)
inLeft.push_back(*it);
else if(k == 1)
inRight.push_back(*it);
if(it == i)
k = 1;
}
//3、求左右子树的前序遍历子序列;
k = 0;
vector<int>::iterator ite;
for(it = pre.begin()+1; it != pre.end(); it++)
{
for(ite = inLeft.begin(); ite != inLeft.end(); ite++)
{
if(*it == *ite)
{
preLeft.push_back(*it);
k = 1;
}
}
if(k == 0)
{
preRight.push_back(*it);
}
k = 0;
}
//根据遍历序列求出跟的左右节点;
node->left = reConstructBinaryTree(preLeft,inLeft);
node->right = reConstructBinaryTree(preRight,inRight);
//返回节点地址;
return node;
}
};
/***后序遍历***左右根***/
void posOrderRecur(TreeNode *head){
if(head==NULL) return ;
posOrderRecur(head->left);
posOrderRecur(head->right);
if(head==root)
printf("%d\n",head->val);
else
printf("%d ",head->val);
}
int main()
{
int n;
Solution so;
while(scanf("%d",&n)>0)
{
root=new TreeNode(NULL);
vector<int> a,b;
int x;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
a.push_back(x);
}
for(int i=0;i<n;i++)
{
scanf("%d",&x);
b.push_back(x);
}
root=so.reConstructBinaryTree(a,b);
TreeNode *h=root;
posOrderRecur(h);
}
return 0;
}
然后在提供一种数组递归的,利用指针,会方便很多呢。
46ms AC
#include<stdio.h>
#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode *root;
TreeNode *Creat(int *pre,int *in,int n)
{
TreeNode *s;
for(int i=0;i<n;i++)
{
if(pre[0]==in[i])
{
s=new TreeNode(in[i]);
//中序历遍中在根节点左边的都是左子树上的
s->left=Creat(pre+1,in,i);
//在根节点右边的,都是右子树上的,右子树需要从i+1开始
s->right=Creat(pre+i+1,in+i+1,n-i-1);
return s;
}
}
return NULL;
}
/***后序遍历***左右根***/
void posOrderRecur(TreeNode *head){
if(head==NULL) return ;
posOrderRecur(head->left);
posOrderRecur(head->right);
if(head==root)
printf("%d\n",head->val);
else
printf("%d ",head->val);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
root=NULL;
int a[2005],b[2005];
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
scanf("%d",&b[i]);
root=Creat(a,b,n);
TreeNode *head=root;
posOrderRecur(head);
}
return 0;
}