问题描述:
/*输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍
历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。*/思路:
1.
前序遍历序列 prev { 1, 2, 4, 7, 3, 5, 6, 8 };
中序遍历序列 vin { 4, 7, 2, 1, 5, 3, 8, 6 };2.
前序:根左右 : 前序往后走是先往左走, 左完了之后才是右
中序:左根右。 中序往上走是先往根走,
在此之前。需要明白:前序的第一个节点就是中序的根结点,所以: 1 的左边是其左子树 右边是其右子树3.
从而得到了大概的粗略的左右子树,但毕竟仅仅由上面是无法知道1的左右子树是怎样的排列细节
接下来可以这样想:依靠上面的方式我得到了一个粗略的左右子树,那如果我将vin顺序表按前面得到的粗略的左右子树分为两个缩小的顺序表,再根据prev顺序表得到其下一个元素,这个元素对应到缩小后的vin中,不就可以再次得到一个缩小之后的左右子树吗?重复上面的3过程,类似于子问题,所以下面用递归实现。
#pragma once
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x)
: val(x)
, left(NULL)
, right(NULL)
{}
};
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin)
{
size_t index = 0;
return _reConstructBinaryTree(pre,vin,index);
}
TreeNode* _reConstructBinaryTree(vector<int> pre, vector<int> vin,size_t& index)
{
if (index >= pre.size()||vin.size() == 0)
{
return NULL;
}
else
{
TreeNode *_root = new TreeNode(pre[index]);
vector<int> vleft;
vector<int> vright;
int i = 0; //在前序得到一个数,在中序找到对应的位置 i
while (i < vin.size() && vin[i] != pre[index])
{
i++;
}
for (int j = 0; j < i; j++)
{
vleft.push_back(vin[j]) ;
}
for (int j = i+1; j<vin.size(); j++)
{
vright.push_back(vin[j]);
}
index++;
_root->left = _reConstructBinaryTree(pre,vleft,index);
_root->right = _reConstructBinaryTree(pre, vright, index);
return _root;
}
}
};
void test()
{
int pre[8] = { 1, 2, 4, 7, 3, 5, 6, 8 };
vector<int> p(pre,pre+8);
int vin[8] = { 4, 7, 2, 1, 5, 3, 8, 6 };
vector<int > v(vin,vin+8) ;
Solution s;
s.reConstructBinaryTree(p,v);
}