问题描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:实际上是之前看过LeetCode上面的解法,二叉树的总体解法思想都用递归比较稳妥,改题目考查的是前序遍历和中序遍历的结构,前序遍历的第一个值是根节点的值,而中序遍历的最中间的值是根节点的值,因此根节点可以将中序遍历分为两半,其中左边的所有元素(个数为leftsize)是左子树的中序遍历的结果, 右边的所有元素是右子树的中序遍历的结果,对于前序遍历序列,越过第一个根节点后的leftsize个元素为左子树前序遍历的结果,剩余的元素为右子树前序遍历的结果,这样可以从而将问题分割化为左右子树的构建,从而递归求解左右子树返回的根节点, 递归终止条件是分割出来的前序遍历和中序遍历的序列左右两边移动到同一位置,此时该遍历树为空子树。
代码如下:
class Solution { private: template<typename InputIterator> TreeNode* construct(InputIterator startPre,InputIterator endPre,InputIterator startVin,InputIterator endVin) { if(endPre==startPre || endVin==startVin) return nullptr; TreeNode* root = new TreeNode(*startPre); auto inRootPos = find(startVin,endVin,*startPre);//找出中序遍历中根节点的位置,也就是分割左右子树遍历结果的分界点 auto leftSize = distance(startVin,inRootPos);//计算中序遍历左边有多少元素 也就是左子树有多少结点 auto leftPreStart = startPre+1; auto leftPreEnd = startPre+leftSize+1; auto rightPreStart = startPre+leftSize+1; auto rightPreEnd = endPre; auto leftVinStart = startVin; auto leftVinEnd = inRootPos; auto righrVinStart = inRootPos+1; auto rightVinEnd = endVin; //分别计算出左右子树的遍历结果的左右界限 root->left = construct(leftPreStart,leftPreEnd,leftVinStart,leftVinEnd);//计算左子树 root->right = construct(rightPreStart,rightPreEnd,righrVinStart,rightVinEnd);//计算右子树 return root; } public: TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) { return construct(pre.begin(),pre.end(),vin.begin(),vin.end()); } };