面试题7:重建二叉树

一、题目

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出如所示的二叉树并输出它的头结点。

                              1
                           /     \
                          2       3  
                         /       / \
                        4       5   6
                         \         /

                          7       8

图1. 根据前序遍历前序遍历序列{1,2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6}重建的二叉树。

二、解法

    分析:前序遍历的第一个数字1就是根节点的值,扫描中序遍历序列,就能确定根节点的值的位置,根据中序遍历的特点,在根节点的值1前面的三个数字都是左子树节点的值,位于1后面的数字都是右子树节点的值。

    由于在中序遍历中,有3个数字是左子树节点的值,因此左子树有3个节点,同样在前序遍历序列中,根节点后面的3个数字就是3个左子树节点的值,在后面的所有数字都是右子树节点的值,这样我们就在前序遍历和中序遍历两个序列中分别找到了左、右子树对应的子序列。

    既然我们已经分别找到了左右子树的前序遍历序列和中序遍历序列,我们也可以用同样的方法分别构建左右子树,也就是说接下来的事情可以用递归的方法去完成。

#include<iostream>
#include<vector>

using namespace std;

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x):val(x), left(NULL),right(NULL){}
};

struct TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> in)
{
	if (pre.size() == NULL)
		return NULL;
	TreeNode* root = new TreeNode(pre[0]);
	int i;
	for (i = 0; i < in.size() && in[i] != pre[0]; i++);
	vector<int> pre_left, in_left, pre_right, in_right;
	int pre_i  = 1;
	for (int j  = 0; j < in.size(); j++)
	{
		if(j< i)
		{
			in_left.push_back(in[j]);
			pre_left.push_back(pre[pre_i]);
			pre_i++;
		}
		else if(j>i)
		{
			in_right.push_back(in[j]);
			pre_right.push_back(pre[pre_i]);
			pre_i++;
		}
	}
	root->left = reConstructBinaryTree(pre_left, in_left);
	root->right = reConstructBinaryTree(pre_right, in_right);
	return root;
}
void preOrder(TreeNode* root)
{
	if (root == nullptr)
		return;
	cout << root->val<<endl;
	preOrder(root->left);
	preOrder(root->right);
}

int main()
{
	vector<int> pre = { 1,2,4,7,3,5,6,8};
	vector<int> in  = { 4,7,2,1,5,3,8,6};
	TreeNode* root = reConstructBinaryTree(pre, in);
	preOrder(root);
	
	system("pause");
}

上述代码需要分配额外的空间,以下代码不需要额外分配空间

#include<iostream>
#include<vector>

using namespace std;

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x):val(x), left(NULL),right(NULL){}
};

void preOrder(TreeNode* root)
{
	if (root == nullptr)
		return;
	cout << root->val<<endl;
	preOrder(root->left);
	preOrder(root->right);


}


TreeNode* ConstructCore(vector<int> pre, int startPre, int endPre, vector<int> vin, int startIn, int endIn) {
	int rootValue = pre[startPre];
	TreeNode* root = new TreeNode(rootValue);
	if (startPre == endPre)
	{
		if (startIn == endIn && pre[startPre] == vin[startIn])
			return root;
		else
			throw std::exception("invalid input");
	}
	int rootIn = startIn;
	while (rootIn <= endIn && vin[rootIn] != rootValue)
		++rootIn;
	if (rootIn == endIn && vin[rootIn] != rootValue)
		throw std::exception("invalid input");
	int leftLength = rootIn - startIn;
	int leftPreorderEnd = startPre + leftLength;
	if (leftLength>0)
	{
		root->left = ConstructCore(pre, startPre + 1, leftPreorderEnd, vin, startIn, rootIn - 1);
	}
	if (leftLength<endPre - startPre)
		root->right = ConstructCore(pre, leftPreorderEnd + 1, endPre,
			vin, rootIn + 1, endIn);
	return root;

}

TreeNode* reConstructBinaryTree1(vector<int> pre, vector<int> vin) {
	if (pre.size() == 0 || vin.size() == 0)
		return nullptr;
	return ConstructCore(pre, 0, pre.size() - 1, vin, 0, vin.size()-1);
}



int main()
{
	vector<int> pre = { 1,2,4,7,3,5,6,8};
	vector<int> in  = { 4,7,2,1,5,3,8,6};
	TreeNode* root = reConstructBinaryTree1(pre, in);
	preOrder(root);
	
	system("pause");
}

猜你喜欢

转载自blog.csdn.net/sinat_36161667/article/details/80717467