题目描述
- 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出二叉树并输出它的头结点。
算法分析
- 先序遍历第一个位置肯定是根节点node, 中序遍历的根节点位置在中间p,在p左边的肯定是node的左子树的中序数组,p右边的肯定是node的右子树的中序数组;
- 另一方面,先序遍历的第二个位置到p,也是node左子树的先序子数组,剩下p右边的就是node的右子树的先序子数组,把四个数组找出来,分左右递归调用即可。
提交代码:
class Solution { public: TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) { if (pre.empty() || vin.empty() || pre.size() != vin.size()) return nullptr; TreeNode* root = reConstructBinaryTreeCore( pre.begin(), pre.end(), vin.begin(), vin.end()); return root; } TreeNode* reConstructBinaryTreeCore(vector<int>::iterator start_pre, vector<int>::iterator end_pre, vector<int>::iterator start_vin, vector<int>::iterator end_vin) { if (start_pre == end_pre || start_vin == end_vin) return nullptr; int rootVal = *start_pre; int rootIndex = getIndexInVin(rootVal, start_vin, end_vin); // 提交时需要去除 if (rootIndex == -1) throw exception("Invalid input."); TreeNode* root = new TreeNode(rootVal); root->left = reConstructBinaryTreeCore(start_pre + 1, start_pre + rootIndex + 1, start_vin, start_vin + rootIndex); root->right = reConstructBinaryTreeCore(start_pre + rootIndex + 1, end_pre, start_vin + rootIndex + 1, end_vin); return root; } //获取中序遍历中根节点的位置,也是左子数的长度 int getIndexInVin(int rootVal, vector<int>::iterator start_vin, vector<int>::iterator end_vin) { for (auto iter = start_vin; iter < end_vin; ++iter) { if (rootVal == *iter) return (iter - start_vin); } // 两个序列不同 return -1; } };
测试代码:
#include<iostream> #include<vector> #include "TreeNode.h" using namespace std; /* // 面试题7:重建二叉树 // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输 // 入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1, // 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出 // 二叉树并输出它的头结点。 */ // ====================测试代码==================== void Test(char* testName, vector<int> &preorder, vector<int> &inorder) { Solution s; if (testName != nullptr) printf("%s begins:\n", testName); printf("The preorder sequence is: "); for (int i = 0; i < preorder.size(); ++i) printf("%d ", preorder[i]); printf("\n"); printf("The inorder sequence is: "); for (int i = 0; i < inorder.size(); ++i) printf("%d ", inorder[i]); printf("\n"); try { TreeNode* root = s.reConstructBinaryTree(preorder, inorder); PrintTree(root); DestroyTree(root); } catch (std::exception& exception) { printf("Invalid Input.\n"); } } // 普通二叉树 // 1 // / \ // 2 3 // / / \ // 4 5 6 // \ / // 7 8 void Test1() { vector<int> preorder = { 1, 2, 4, 7, 3, 5, 6, 8 }; vector<int> inorder = { 4, 7, 2, 1, 5, 3, 8, 6 }; Test("Test1", preorder, inorder); } // 所有结点都没有右子结点 // 1 // / // 2 // / // 3 // / // 4 // / // 5 void Test2() { vector<int> preorder = { 1, 2, 3, 4, 5 }; vector<int> inorder = { 5, 4, 3, 2, 1 }; Test("Test2", preorder, inorder); } // 所有结点都没有左子结点 // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test3() { vector<int> preorder = { 1, 2, 3, 4, 5 }; vector<int> inorder = { 1, 2, 3, 4, 5 }; Test("Test3", preorder, inorder); } // 树中只有一个结点 void Test4() { vector<int> preorder = { 1 }; vector<int> inorder = { 1 }; Test("Test4", preorder, inorder); } // 完全二叉树 // 1 // / \ // 2 3 // / \ / \ // 4 5 6 7 void Test5() { vector<int> preorder = { 1, 2, 4, 5, 3, 6, 7 }; vector<int> inorder = { 4, 2, 5, 1, 6, 3, 7 }; Test("Test5", preorder, inorder); } // 输入空指针 void Test6() { Test("Test6", vector<int>(), vector<int>()); } // 输入的两个序列不匹配 void Test7() { vector<int> preorder = { 1, 2, 4, 5, 3, 6, 7 }; vector<int> inorder = { 4, 2, 8, 1, 6, 3, 7 }; Test("Test7: for unmatched input", preorder, inorder); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); return 0; }