Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4e34407

Browse files
feat: add solutions to lc problem: No.0889 (doocs#2355)
1 parent b9ad39b commit 4e34407

File tree

7 files changed

+431
-130
lines changed

7 files changed

+431
-130
lines changed

‎solution/0800-0899/0889.Construct Binary Tree from Preorder and Postorder Traversal/README.md‎

Lines changed: 152 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,27 @@
4646

4747
### 方法一:递归
4848

49-
1. 以 preorder 的第一个元素或 postorder 的最后一个元素为根节点的值。
50-
2. 以 preorder 的第二个元素作为左子树的根节点,在 postorder 中找到该元素的索引 i,然后基于索引 i 可以计算出左右子树的长度。
51-
3. 最后基于左右子树的长度,分别划分出前序和后序遍历序列中的左右子树,递归构造左右子树即可。
49+
前序遍历的顺序是:根节点 -> 左子树 -> 右子树,后序遍历的顺序是:左子树 -> 右子树 -> 根节点。
50+
51+
因此,二叉树的根节点一定是前序遍历的第一个节点,也是后序遍历的最后一个节点。
52+
53+
接下来,我们需要确定二叉树的左子树范围和右子树范围。
54+
55+
如果二叉树有左子树,那么左子树的根节点一定是前序遍历的第二个节点;如果二叉树没有左子树,那么前序遍历的第二个节点一定是右子树的根节点。由于这两种情况下,后序遍历的结果是一样的,因此,我们可以把前序遍历的第二个节点作为左子树的根节点,然后找到它在后序遍历中的位置,这样就确定了左子树的范围。
56+
57+
具体地,我们设计一个递归函数 $dfs(a, b, c, d),ドル其中 $[a, b]$ 表示前序遍历的范围,而 $[c, d]$ 表示后序遍历的范围。这个函数的功能是根据前序遍历 $[a, b]$ 和后序遍历 $[c, d]$ 构造出二叉树的根节点。那么答案就是 $dfs(0, n - 1, 0, n - 1),ドル其中 $n$ 是前序遍历的长度。
58+
59+
函数 $dfs(a, b, c, d)$ 的执行步骤如下:
60+
61+
1. 如果 $a > b,ドル说明范围为空,直接返回空节点。
62+
1. 否则,我们构造一个新的节点 $root,ドル它的值为前序遍历中的第一个节点的值,也就是 $preorder[a]$。
63+
1. 如果 $a$ 等于 $b,ドル说明 $root$ 没有左子树也没有右子树,直接返回 $root$。
64+
1. 否则,左子树的根节点的值为 $preorder[a + 1],ドル我们在后序遍历中找到 $preorder[a + 1]$ 的位置,记为 $i$。那么左子树的节点个数 $m = i - c + 1,ドル由此可知左子树在前序遍历中的范围是 $[a + 1, a + m],ドル后序遍历中的范围是 $[c, i],ドル右子树在前序遍历中的范围是 $[a + m + 1, b],ドル后序遍历中的范围是 $[i + 1, d - 1]$。
65+
1. 知道了左右子树的范围,我们就可以递归地重建左右子树,然后将左右子树的根节点分别作为 $root$ 的左右子节点。最后返回 $root$。
66+
67+
在函数 $dfs(a, b, c, d)$ 中,我们需要用到一个哈希表 $pos,ドル它存储了后序遍历中每个节点的位置。在函数的开头,我们可以先计算出这个哈希表,这样就可以在 $O(1)$ 的时间内找到任意节点在后序遍历中的位置。
68+
69+
时间复杂度 $O(n),ドル空间复杂度 $O(n)$。其中 $n$ 是节点数。
5270

5371
<!-- tabs:start -->
5472

@@ -62,22 +80,68 @@
6280
class Solution:
6381
def constructFromPrePost(
6482
self, preorder: List[int], postorder: List[int]
65-
) -> TreeNode:
66-
n = len(preorder)
67-
if n == 0:
68-
return None
69-
root = TreeNode(preorder[0])
70-
if n == 1:
71-
return root
72-
for i in range(n - 1):
73-
if postorder[i] == preorder[1]:
74-
root.left = self.constructFromPrePost(
75-
preorder[1 : 1 + i + 1], postorder[: i + 1]
76-
)
77-
root.right = self.constructFromPrePost(
78-
preorder[1 + i + 1 :], postorder[i + 1 : -1]
79-
)
83+
) -> Optional[TreeNode]:
84+
def dfs(a: int, b: int, c: int, d: int) -> Optional[TreeNode]:
85+
if a > b:
86+
return None
87+
root = TreeNode(preorder[a])
88+
if a == b:
8089
return root
90+
i = pos[preorder[a + 1]]
91+
m = i - c + 1
92+
root.left = dfs(a + 1, a + m, c, i)
93+
root.right = dfs(a + m + 1, b, i + 1, d - 1)
94+
return root
95+
96+
pos = {x: i for i, x in enumerate(postorder)}
97+
return dfs(0, len(preorder) - 1, 0, len(postorder) - 1)
98+
```
99+
100+
```java
101+
/**
102+
* Definition for a binary tree node.
103+
* public class TreeNode {
104+
* int val;
105+
* TreeNode left;
106+
* TreeNode right;
107+
* TreeNode() {}
108+
* TreeNode(int val) { this.val = val; }
109+
* TreeNode(int val, TreeNode left, TreeNode right) {
110+
* this.val = val;
111+
* this.left = left;
112+
* this.right = right;
113+
* }
114+
* }
115+
*/
116+
class Solution {
117+
private Map<Integer, Integer> pos = new HashMap<>();
118+
private int[] preorder;
119+
private int[] postorder;
120+
121+
public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
122+
this.preorder = preorder;
123+
this.postorder = postorder;
124+
for (int i = 0; i < postorder.length; ++i) {
125+
pos.put(postorder[i], i);
126+
}
127+
return dfs(0, preorder.length - 1, 0, postorder.length - 1);
128+
}
129+
130+
private TreeNode dfs(int a, int b, int c, int d) {
131+
if (a > b) {
132+
return null;
133+
}
134+
TreeNode root = new TreeNode(preorder[a]);
135+
if (a == b) {
136+
return root;
137+
}
138+
int i = pos.get(preorder[a + 1]);
139+
int m = i - c + 1;
140+
root.left = dfs(a + 1, a + m, c, i);
141+
root.right = dfs(a + m + 1, b, i + 1, d - 1);
142+
return root;
143+
}
144+
}
81145
```
82146

83147
```cpp
@@ -94,23 +158,27 @@ class Solution:
94158
*/
95159
class Solution {
96160
public:
97-
unordered_map<int, int> postMap;
98161
TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) {
99-
for (int i = 0; i < postorder.size(); i++) {
100-
postMap[postorder[i]] = i;
162+
unordered_map<int, int> pos;
163+
int n = postorder.size();
164+
for (int i = 0; i < n; ++i) {
165+
pos[postorder[i]] = i;
101166
}
102-
return build(preorder, 0, preorder.size() - 1, postorder, 0, postorder.size() - 1);
103-
}
104-
105-
TreeNode* build(vector<int>& preorder, int prel, int prer, vector<int>& postorder, int postl, int postr) {
106-
if (prel > prer) return nullptr;
107-
TreeNode* root = new TreeNode(preorder[prel]);
108-
if (prel == prer) return root;
109-
int leftRootIndex = postMap[preorder[prel + 1]];
110-
int leftLength = leftRootIndex - postl + 1;
111-
root->left = build(preorder, prel + 1, prel + leftLength, postorder, postl, leftRootIndex);
112-
root->right = build(preorder, prel + leftLength + 1, prer, postorder, leftRootIndex + 1, postr - 1);
113-
return root;
167+
function<TreeNode*(int, int, int, int)> dfs = [&](int a, int b, int c, int d) -> TreeNode* {
168+
if (a > b) {
169+
return nullptr;
170+
}
171+
TreeNode* root = new TreeNode(preorder[a]);
172+
if (a == b) {
173+
return root;
174+
}
175+
int i = pos[preorder[a + 1]];
176+
int m = i - c + 1;
177+
root->left = dfs(a + 1, a + m, c, i);
178+
root->right = dfs(a + m + 1, b, i + 1, d - 1);
179+
return root;
180+
};
181+
return dfs(0, n - 1, 0, n - 1);
114182
}
115183
};
116184
```
@@ -125,29 +193,68 @@ public:
125193
* }
126194
*/
127195
func constructFromPrePost(preorder []int, postorder []int) *TreeNode {
128-
postMap := make(map[int]int)
129-
for index, v := range postorder {
130-
postMap[v] = index
196+
pos := map[int]int{}
197+
for i, x := range postorder {
198+
pos[x] = i
131199
}
132-
var dfs func(prel, prer, postl, postr int) *TreeNode
133-
dfs = func(prel, prer, postl, postr int) *TreeNode {
134-
if prel > prer {
200+
var dfs func(int, int, int, int) *TreeNode
201+
dfs = func(a, b, c, d int) *TreeNode {
202+
if a > b {
135203
return nil
136204
}
137-
root := &TreeNode{Val: preorder[prel]}
138-
if prel == prer {
205+
root := &TreeNode{Val: preorder[a]}
206+
if a == b {
139207
return root
140208
}
141-
leftRootIndex := postMap[preorder[prel+1]]
142-
leftLength := leftRootIndex - postl + 1
143-
root.Left = dfs(prel+1, prel+leftLength, postl, leftRootIndex)
144-
root.Right = dfs(prel+leftLength+1, prer, leftRootIndex+1, postr-1)
209+
i := pos[preorder[a+1]]
210+
m := i - c + 1
211+
root.Left = dfs(a+1, a+m, c, i)
212+
root.Right = dfs(a+m+1, b, i+1, d-1)
145213
return root
146214
}
147215
return dfs(0, len(preorder)-1, 0, len(postorder)-1)
148216
}
149217
```
150218

219+
```ts
220+
/**
221+
* Definition for a binary tree node.
222+
* class TreeNode {
223+
* val: number
224+
* left: TreeNode | null
225+
* right: TreeNode | null
226+
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
227+
* this.val = (val===undefined ? 0 : val)
228+
* this.left = (left===undefined ? null : left)
229+
* this.right = (right===undefined ? null : right)
230+
* }
231+
* }
232+
*/
233+
234+
function constructFromPrePost(preorder: number[], postorder: number[]): TreeNode | null {
235+
const pos: Map<number, number> = new Map();
236+
const n = postorder.length;
237+
for (let i = 0; i < n; ++i) {
238+
pos.set(postorder[i], i);
239+
}
240+
const dfs = (a: number, b: number, c: number, d: number): TreeNode | null => {
241+
if (a > b) {
242+
return null;
243+
}
244+
const root = new TreeNode(preorder[a]);
245+
if (a === b) {
246+
return root;
247+
}
248+
const i = pos.get(preorder[a + 1])!;
249+
const m = i - c + 1;
250+
root.left = dfs(a + 1, a + m, c, i);
251+
root.right = dfs(a + m + 1, b, i + 1, d - 1);
252+
return root;
253+
};
254+
return dfs(0, n - 1, 0, n - 1);
255+
}
256+
```
257+
151258
<!-- tabs:end -->
152259

153260
<!-- end -->

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /