从中序与后序遍历序列构造二叉树
题目描述
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
题目分析
我们知道后序遍历是:左右中,也就是说永远是中间的根节点在最后,这样我们就能确定整棵树的根节点在postorder[postorder.size()-1]
处(数组末尾)。
而中序遍历是:左中右,也就是说先遍历左子树,再访问中间的根节点,最后遍历右子树。那么通过后序节点确定的根节点,我们可以将中序遍历结果切割出左子树和右子树。最后,分别根据我们切割出的中序左子树和中序右子树的节点数量(数组大小)去确定后序左子树和后序右子树,因为他们的数量/大小一定是对应的。
通过上述分析,我们可以结合中序和后序遍历结果递归分割出左子树和右子树来进行处理,就能还原整体二叉树。
cpp代码
/**
* Definition for a binary tree node.
* 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) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(postorder.size()==0) return NULL;
// 后序遍历数组的最后一个元素就是根节点
int rootValue = postorder[postorder.size()-1];
TreeNode* root = new TreeNode(rootValue);
// 如果后序遍历数组只有一个元素,那么这个数只有一个节点
if(postorder.size()==1) return root;
// 找中序遍历数组中根结点处的切割点
int delimiterIndex;
for(delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
if(inorder[delimiterIndex] == rootValue) break;
}
// 切割中序数组,得到:中序左数组和中序右数组
vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end());
// 切割后序数组,得到:后序左数组和后序右数组
postorder.resize(postorder.size() - 1); // 舍弃末尾元素(根节点)
vector<int> leftPostOrder(postorder.begin(), postorder.begin() + leftInorder.size());
vector<int> rightPostOrder(postorder.begin() + leftInorder.size(), postorder.end());
// 单层递归
root->left = buildTree(leftInorder, leftPostOrder);
root->right = buildTree(rightInorder, rightPostOrder);
return root;
}
};
从前序与中序遍历序列构造二叉树
题目描述
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
题目分析
跟上题是一样的思路,只不过后序遍历是根节点在末尾,而前序遍历根节点在开头。
cpp代码
/**
* Definition for a binary tree node.
* 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) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
// 前序是中左右,根节点在前序的开头
if(preorder.size()==0) return NULL;
int rootValue = preorder[0];
TreeNode* root = new TreeNode(rootValue);
if(preorder.size()==1) return root;
// 找根节点的index来分割中序
int delimiterIndex;
for(delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++){
if(inorder[delimiterIndex] == rootValue) break;
}
// 分割中序
vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end());
// 分割前序
vector<int> leftPreorder(preorder.begin() + 1, preorder.begin() + 1 + leftInorder.size());
vector<int> rightPreorder(preorder.begin() + 1 + leftInorder.size(), preorder.end());
// 单层递归
root->left = buildTree(leftPreorder, leftInorder);
root->right = buildTree(rightPreorder, rightInorder);
return root;
}
};