1. 题目来源
链接:106. 从中序与后序遍历序列构造二叉树
力扣题解:官方题解:从中序与后序遍历序列构造二叉树
2. 题目解析
参考原有博文即可:前中,中后,都可以建树成功! [M二叉树] lc105. 从前序与中序遍历序列构造二叉树(递归建树+迭代建树+经典问题)
十分经典的问题哈,这里主要记录下还有一种迭代的写法,迭代写法可以去参考官方题解中的写法,确实第一次见这个巧妙的迭代建树的写法。
这里其实用哈希表记录位置才能算是 O(n) 否则用循环来做的话,可能达到 O(n^2)
总结:
- 经过这两道题目可以知道,中+后、前+中 树中节点值唯一,这两个情况下,是可以 唯一 确定一颗二叉树的。但是,前+后 是无法唯一确定的,因为前、后只能知道根节点是哪个,但不知道对应的左右子树,就无法确定了。主要还是因为 前、后 序没有划分左右子树的能力,所以需要中序遍历的帮助。
- 中序+层序 也能构造二叉树,可见 aw1259 题目。这个不做要求,较为复杂。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
/**
* 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) {
return build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
}
TreeNode* build(vector<int> &inorder, int iL, int iR, vector<int> &postorder, int pL, int pR) {
if (pL > pR || iL > iR) return NULL;
int i = iL;
for (; i <= iR; i ++ ) {
if (postorder[pR] == inorder[i])
break;
}
TreeNode *node = new TreeNode(postorder[pR]);
node->left = build(inorder, iL, i - 1, postorder, pL, pL + i - iL - 1);
node->right = build(inorder, i + 1, iR, postorder, pL + i - iL, pR - 1);
return node;
}
};
哈希表记录位置:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
unordered_map<int,int> pos;
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
int n = inorder.size();
for (int i = 0; i < n; i ++ )
pos[inorder[i]] = i;
return dfs(postorder, inorder, 0, n - 1, 0, n - 1);
}
// pl, pr 表示当前子树后序遍历在数组中的位置
// il, ir 表示当前子树中序遍历在数组中的位置
TreeNode* dfs(vector<int>&post, vector<int>&in, int pl, int pr, int il, int ir)
{
if (pl > pr) return NULL;
int k = pos[post[pr]] - il;
TreeNode* root = new TreeNode(post[pr]);
root->left = dfs(post, in, pl, pl + k - 1, il, il + k - 1);
root->right = dfs(post, in, pl + k, pr - 1, il + k + 1, ir);
return root;
}
};