LeetCode 利用前中后序遍历三种中的两种构建树

题意

https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。

https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
给定一棵树的中序遍历 inorder 与后序遍历 postorder。请构造二叉树并返回其根节点。

https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-postorder-traversal
给定一棵树的前序遍历 preorder 与后序遍历 postorder。请构造二叉树并返回其根节点。

解法

也是经典老题了
记得我之前考PAT的时候的最后一题
当时没有完全调出来
现在能一下子通过还是很开心的
思路其实众所周知了,前序遍历的第一个节点在中序遍历序列中切分为左子树和右子树
递归执行即可
主要在计算左右子树的节点个数的时候有点繁琐 需要仔细一点
单独把左子树的节点个数拿出来计算,下一次递归的时候传入
三类不同的构造,形式相同,做法相似

代码

前序+中序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int l, int r, int a, int b) {
if (l > r) return nullptr;
TreeNode* root = new TreeNode(preorder[l]);
if (l == r) return root;
int mid = 0;
for (int i = a; i <= b; i++) {
if (inorder[i] == root -> val) {
mid = i;
break;
}
}
int pre = mid - a; // 左子树的长度
root -> left = build(preorder, inorder, l + 1, l + pre, a, mid - 1);
root -> right = build(preorder, inorder, l + pre + 1, r, mid + 1, b);
return root;

}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (preorder.empty()) return nullptr;
int siz = preorder.size();
return build(preorder, inorder, 0, siz - 1, 0, siz - 1);

}
};

中序+后序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
unordered_map<int, int> in;
TreeNode* construct(vector<int>& inorder, vector<int>& postorder, int l, int r, int a, int b) {
if (l > r) return nullptr;
TreeNode* root = new TreeNode(postorder[b]);
if (l == r) return root;
int mid = in[postorder[b]];
int left_tree = mid - l; // 左子树长度
root -> left = construct(inorder, postorder, l, mid - 1, a, a + left_tree - 1);
root -> right = construct(inorder, postorder, mid + 1, r, a + left_tree, b - 1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
int n = inorder.size();
for (int i = 0; i < n; i++) {
in[inorder[i]] = i;
}
return construct(inorder, postorder, 0, n - 1, 0, n - 1);

}
};

前序+后序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
unordered_map<int, int> post;
TreeNode* construct(vector<int>& preorder, vector<int>& postorder, int l, int r, int a, int b) {
if (l > r) return nullptr;
TreeNode* root = new TreeNode(preorder[l]);
if (l == r) return root;
int loc = post[preorder[l + 1]];
int left_tree = loc - a + 1; // 左子树长度
root -> left = construct(preorder, postorder, l + 1, l + left_tree, a, loc);
root -> right = construct(preorder, postorder, l + left_tree + 1, r, loc + 1, b);
return root;
}
TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) {
int n = preorder.size();
for (int i = 0; i < n; i++) {
post[postorder[i]] = i;
}
return construct(preorder, postorder, 0, n - 1, 0, n - 1);
}
};