一 题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
二 解法1
1 分析
重建二叉树的经典做法是和遍历二叉树一样的思想,不管是前序、中序或者是后序遍历都是利用递归的思想。本题中根据前序遍历、中序遍历的特点,例如:前序遍历序列首元素尾二叉树的根结点,中序遍历中根结点左侧为左子树结点、右侧为右子树结点。
递归函数的重点有两个:①递归公式:二叉树 = 根节点 + 左子树 + 右子树;②递归终止条件:在本题中,二叉树的遍历序列为空时,则递归结束。所以本题难点是如何截取前序、中序遍历序列的左右子树从而变成递归的起始条件。
2 代码
1 /** 2 * Definition for binary tree 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) { 13 /*按照根结点、左子树、右子树的顺序重建二叉树,可以用到递归思想*/ 14 15 //输入检测 16 if (!pre.size() || !vin.size()) //如果前序遍历或中序遍历有空序列 17 return nullptr; 18 19 //重建二叉树 20 //创建根节点 21 TreeNode *pRootNode = new TreeNode(pre[0]); 22 //截取前序遍历和中序遍历的左右子树序列 23 int count = 0; 24 for (auto i : vin) { 25 if (pre[0] == i) 26 break; 27 ++count; 28 } 29 vector<int> preLeft(pre.cbegin() + 1, pre.cbegin() + count + 1); //前序遍历左子树序列 30 vector<int> preRight(pre.cbegin() + count + 1, pre.cend()); //前序遍历右子树序列 31 vector<int> vinLeft(vin.cbegin(), vin.cbegin() + count); //中序遍历左子树序列 32 vector<int> vinRight(vin.cbegin() + count + 1, vin.cend()); //中序遍历左子树序列 33 //创建左子树 34 if (preLeft.size()) 35 pRootNode->left = reConstructBinaryTree(preLeft, vinLeft); 36 //创建右子树 37 if (preRight.size()) 38 pRootNode->right = reConstructBinaryTree(preRight, vinRight); 39 40 return pRootNode; 41 } 42 };
3 代码实现时的模糊点
① vector容器的拷贝初始化。例如vector<int> pre{1, 2, 3, 4, 5, 6}; 要求拷贝前三个数字也就是1, 2, 3
1 vector<int> pre{1, 2, 3, 4, 5, 6}; 2 vector<int> preLeft (pre.cbegin(), pre.begin() + 3); //千万要注意这里是+3,也就是4的位置,结尾迭代器为最后拷贝元素的下一个位置
② 重建二叉树的方法
该篇博客是自己的学习总结,水平有限,如有错误,欢迎讨论!