46
46
47
47
### 方法一:递归
48
48
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$ 是节点数。
52
70
53
71
<!-- tabs:start -->
54
72
62
80
class Solution :
63
81
def constructFromPrePost (
64
82
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:
80
89
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
+ }
81
145
```
82
146
83
147
``` cpp
@@ -94,23 +158,27 @@ class Solution:
94
158
*/
95
159
class Solution {
96
160
public:
97
- unordered_map<int, int> postMap;
98
161
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;
101
166
}
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);
114
182
}
115
183
};
116
184
```
@@ -125,29 +193,68 @@ public:
125
193
* }
126
194
*/
127
195
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
131
199
}
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 {
135
203
return nil
136
204
}
137
- root := &TreeNode{Val: preorder[prel ]}
138
- if prel == prer {
205
+ root := &TreeNode{Val: preorder[a ]}
206
+ if a == b {
139
207
return root
140
208
}
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)
145
213
return root
146
214
}
147
215
return dfs(0, len(preorder)-1, 0, len(postorder)-1)
148
216
}
149
217
```
150
218
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
+
151
258
<!-- tabs: end -->
152
259
153
260
<!-- end -->
0 commit comments