从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
解题思路
通过递归的方法,不断缩小树的范围,将树拆解到叶子,再将叶子赋值到左或者右子树上即可。(第一次写题解,多多谅解,哈哈)
前序遍历
由性质可以得到数组最左边一定是右边数据的父节点。
中序遍历
通过前序遍历得到父亲节点后,找到中序数组中节点的位置,该位置的左边数据都是左子树,右边数据是右子树。通过位置的计算就可以得到该父节点的左子树个数和右子树个数。
代码
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
map<int, int> mapIn;
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (!preorder.size() || !inorder.size() ||preorder.size() != inorder.size())
return NULL;
// 将中序遍历的数据的下标放在map中,方便查找
for (int i = 0; i < inorder.size(); i++){
mapIn[inorder[i]] = i;
}
return buildTreeCore(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* buildTreeCore(vector<int>& preorder, vector<int>& inorder,
int preBegin, int preEnd, int inBegin, int inEnd) {
// 递归退出条件
if (preBegin > preEnd) return NULL;
// 申请节点
TreeNode * root = new TreeNode(preorder[preBegin]);
// 只有一个节点(或者叶子结点)
if (preBegin == preEnd) return root;
// 计算左子树的长度
int leftLen = mapIn[root->val] - inBegin;
int leftEndIndex = preBegin + leftLen;
// 有左子树先构建左子树
if (leftLen > 0) {
root->left = buildTreeCore(preorder, inorder, preBegin + 1, preBegin + leftLen, inBegin, inBegin + leftLen - 1);
}
// 构建右子树
if(preEnd - leftEndIndex > 0){
root->right = buildTreeCore(preorder, inorder, preBegin + leftLen + 1, preEnd, mapIn[root->val] + 1, inEnd);
}
return root;
}
};