版权声明:所有的博客都是作为个人笔记的。。。。。。 https://blog.csdn.net/qq_35976351/article/details/82779869
问题描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路
该题目用到了递归分治的思想。先序遍历二叉树的第一个节点肯定是根节点,那么在中序序列中找到先序的对应数据的下标。根据前序和中序遍历的性质可知,下标左侧的数据是左子树,下标右侧的数据是右子树。同时,下标左侧元素的个数是左子树元素的个数,所以根据这个来划分先序序列的左子树部分;下标右侧的数据的个数是右子树元素的个数,同理划分前序序列右子树部分。递归的求解左右子树,把子序列放入递归函数中求解。递归终止的情况是没有数据可以划分了,此时返回空值。
AC代码
代码中需要注意的是vector的下标,这是最容易出错的地方,没有把握的情况就找一个简单的例子测试一下。还有,递归的时候vector的数据是拷贝的,这对效率有一定的影响,不过题目是这么给的,肯定不会超时了。
提交代码
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if(pre.size() == 0 || vin.size() == 0) {
return nullptr;
}
int r = 0;
for(r = 0; r < vin.size(); r++) { // 找根节点
if(pre[0] == vin[r]) {
break;
}
}
TreeNode *root = new TreeNode(pre[0]);
vector<int>preleft(pre.begin() + 1, pre.begin() + r + 1); // 左子树前序
vector<int>vinleft(vin.begin(), vin.begin() + r); // 左子树前序中序
vector<int>preright(pre.begin() + r + 1, pre.end()); // 右子树前序
vector<int>vinright(vin.begin() + r + 1, vin.end()); // 右子树中序
root->left = reConstructBinaryTree(preleft, vinleft);
root->right = reConstructBinaryTree(preright, vinright);
return root;
}
};
本地测试代码
#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
// 前序序列建树,空节点输入0
TreeNode* createTree() {
int n;
cin >> n;
if(n == 0) {
return nullptr;
}
TreeNode* r = new TreeNode(n);
r->left = createTree();
r->right = createTree();
}
// 前序遍历
void preOrder(TreeNode* root) {
if(root == nullptr) {
return;
}
cout << root->val << " ";
preOrder(root->left);
preOrder(root->right);
}
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
if(pre.size() == 0 || vin.size() == 0) {
return nullptr;
}
int r = 0;
for(r = 0; r < vin.size(); r++) { // 找根节点
if(pre[0] == vin[r]) {
break;
}
}
TreeNode *root = new TreeNode(pre[0]);
vector<int>preleft(pre.begin() + 1, pre.begin() + r + 1); // 左子树前序
vector<int>vinleft(vin.begin(), vin.begin() + r); // 左子树前序中序
vector<int>preright(pre.begin() + r + 1, pre.end()); // 右子树前序
vector<int>vinright(vin.begin() + r + 1, vin.end()); // 右子树中序
root->left = reConstructBinaryTree(preleft, vinleft);
root->right = reConstructBinaryTree(preright, vinright);
return root;
}
};
int main() {
// 这里是自己建树测试
// TreeNode *r=createTree();
// preOrder(r);
// 测试题目数据
vector<int>pre{1, 2, 3, 4, 5, 6};
vector<int>vin{3, 2, 4, 1, 6, 5};
Solution so = Solution();
TreeNode *r = so.reConstructBinaryTree(pre, vin);
preOrder(r);
return 0;
}