剑指offer4_重建二叉树_题解
重建二叉树
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
示例1
输入
[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值
{1,2,5,3,4,6,7}
分析
方案一:递归算法
前序遍历数组 \(pre\) 的首元素就是二叉树的根节点,根据根节点的值在中序遍历数组 \(vin\) 中找到根节点的位置 \(i\) ,则在中序遍历中根节点位置 \(i\) 左边就是左子树的序列,根节点右边就是右子树的序列
设树一共有 \(n\) 个节点,下标从0开始,易知左子树的结点个数为 \(i\)
左子树的先序序列区间为 \([1,i]\),右子树的先序序列区间为 \([i+1,n-1]\)
左子树的中序遍历区间为 \([0,i-1]\),右子树的中序遍历区间为 \([i+1,n-1]\)
接着往左子树和右子树递归构建二叉树
代码
/**
1.时间复杂度:O(n)
对于每个节点都有创建过程以及根据左右子树重建过程。
2.空间复杂度:O(n)
存储整棵树的开销。
**/
class Solution
{
public:
TreeNode *reConstructBinaryTree(vector<int> pre, vector<int> vin)
{
// 若遍历序列为空,则说明到达叶子节点,返回NULL
if (pre.size() == 0)
{
return NULL;
}
// 创建根节点(根节点必是前序遍历的第一个数)
TreeNode *root = new TreeNode(pre[0]);
// 找到中序遍历根节点所在位置i
int i;
for (i = 0; i < vin.size(); i++)
{
if (vin[i] == pre[0])
break;
}
/**
pre_left: 针对左子树的前序遍历序列
pre_right: 针对右子树的前序遍历序列
vin_left: 针对左子树的中序遍历序列
vin_right: 针对右子树的中序遍历序列
**/
vector<int> pre_left, vin_left, pre_right, vin_right;
// 在前序遍历序列pre中左子树区间为[1,i],右子树区间为[i+1,end]
pre_left.assign(pre.begin() + 1, pre.begin() + i + 1);
pre_right.assign(pre.begin() + i + 1, pre.end());
// 在中序遍历序列vin中左子树区间为[0,i-1],右子树区间为[i+1,end]
vin_left.assign(vin.begin(), vin.begin() + i);
vin_right.assign(vin.begin() + i + 1, vin.end());
// 递归求解根节点的左右子树对应的根节点
root->left = reConstructBinaryTree(pre_left, vin_left);
root->right = reConstructBinaryTree(pre_right, vin_right);
// 返回根节点
return root;
}
};
说明
\(vector::assign\) 用法
用途
为向量分配新内容,替换其当前内容,并相应地修改其大小。
参数\(first,last\)
将迭代器输入序列中的初始位置和最终位置。使用的范围是\([first,last)\),左闭右开,包括 \(first\) 指向的元素,不包括 \(last\) 指向的元素。
Example
// vector assign
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> first;
std::vector<int> second;
std::vector<int> third;
first.assign (7,100); // 7 ints with a value of 100
std::vector<int>::iterator it;
it=first.begin()+1;
second.assign (it,first.end()-1); // the 5 central values of first
int myints[] = {1776,7,4};
third.assign (myints,myints+3); // assigning from array.
std::cout << "Size of first: " << int (first.size()) << '\n';
std::cout << "Size of second: " << int (second.size()) << '\n';
std::cout << "Size of third: " << int (third.size()) << '\n';
return 0;
}
Output
Size of first: 7
Size of second: 5
Size of third: 3