Skip to content

Commit 58a4c04

Browse files
authored
feat: add solutions to lc problems: No.105,106 (doocs#2358)
1 parent 363433d commit 58a4c04

File tree

11 files changed

+299
-299
lines changed

11 files changed

+299
-299
lines changed

solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README.md

+12-9
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,22 @@
4040

4141
## 解法
4242

43-
### 方法一:递归
43+
### 方法一:哈希表 + 递归
4444

45-
前序序列的第一个结点 $preorder[0]$ 为根节点,我们在中序序列中找到根节点的位置 $i$,可以将中序序列划分为左子树 $inorder[0..i]$ 、右子树 $inorder[i+1..]$。
45+
前序序列的第一个节点 $preorder[0]$ 为根节点,我们在中序序列中找到根节点的位置 $k$,可以将中序序列划分为左子树 $inorder[0..k]$ 、右子树 $inorder[k+1..]$。
4646

47-
通过左右子树的区间,可以计算出左、右子树节点的个数,假设为 $m$ 和 $n$。然后在前序节点中,从根节点往后的 $m$ 个节点为左子树,再往后的 $n$ 个节点为右子树。
47+
通过左右子树的区间,可以计算出左、右子树节点的个数,假设为 $a$ 和 $b$。然后在前序节点中,从根节点往后的 $a$ 个节点为左子树,再往后的 $b$ 个节点为右子树。
4848

49-
递归求解即可
49+
因此,我们设计一个函数 $dfs(i, j, n)$,其中 $i$ 和 $j$ 分别表示前序序列和中序序列的起始位置,而 $n$ 表示节点个数。函数的返回值是以 $preorder[i..i+n-1]$ 为前序序列,以 $inorder[j..j+n-1]$ 为中序序列构造出的二叉树
5050

51-
> 前序遍历:先遍历根节点,再遍历左右子树;中序遍历:先遍历左子树,再遍历根节点,最后遍历右子树。
51+
函数 $dfs(i, j, n)$ 的执行过程如下:
5252

53-
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树节点个数。
53+
- 如果 $n \leq 0$,说明没有节点,返回空节点。
54+
- 取出前序序列的第一个节点 $v = preorder[i]$ 作为根节点,然后利用哈希表 $d$ 找到根节点在中序序列中的位置 $k$,那么左子树的节点个数为 $k - j$,右子树的节点个数为 $n - k + j - 1$。
55+
- 递归构造左子树 $l = dfs(i + 1, j, k - j)$ 和右子树 $r = dfs(i + 1 + k - j, k + 1, n - k + j - 1)$。
56+
- 最后返回以 $v$ 为根节点且左右子树分别为 $l$ 和 $r$ 的二叉树。
5457

55-
如果题目中给定的节点值存在重复,那么我们只需要记录每个节点值出现的所有位置,然后递归构建即可
58+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树节点个数
5659

5760
<!-- tabs:start -->
5861

@@ -65,7 +68,7 @@
6568
# self.right = right
6669
class Solution:
6770
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
68-
def dfs(i: int, j: int, n: int):
71+
def dfs(i: int, j: int, n: int) -> Optional[TreeNode]:
6972
if n <= 0:
7073
return None
7174
v = preorder[i]
@@ -308,7 +311,7 @@ var buildTree = function (preorder, inorder) {
308311

309312
<!-- tabs:end -->
310313

311-
### 方法二
314+
如果题目中给定的节点值存在重复,那么我们只需要记录每个节点值出现的所有位置,然后递归构建出所有可能的二叉树即可。
312315

313316
<!-- tabs:start -->
314317

solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README_EN.md

+12-9
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,22 @@
3636

3737
## Solutions
3838

39-
### Solution 1: Recursion
39+
### Solution 1: Hash Table + Recursion
4040

41-
The first node $preorder[0]$ in the preorder sequence is the root node. We find the position $i$ of the root node in the inorder sequence, which divides the inorder sequence into the left subtree $inorder[0..i]$ and the right subtree $inorder[i+1..]$.
41+
The first node $preorder[0]$ in the pre-order sequence is the root node. We find the position $k$ of the root node in the in-order sequence, which can divide the in-order sequence into the left subtree $inorder[0..k]$ and the right subtree $inorder[k+1..]$.
4242

43-
Through the intervals of the left and right subtrees, we can calculate the number of nodes in the left and right subtrees, assumed to be $m$ and $n$ respectively. Then in the preorder nodes, the $m$ nodes following the root node are the left subtree, and the $n$ nodes after that are the right subtree.
43+
Through the intervals of the left and right subtrees, we can calculate the number of nodes in the left and right subtrees, assumed to be $a$ and $b$. Then in the pre-order nodes, the $a$ nodes after the root node are the left subtree, and the $b$ nodes after that are the right subtree.
4444

45-
We can solve this recursively.
45+
Therefore, we design a function $dfs(i, j, n)$, where $i$ and $j$ represent the starting positions of the pre-order sequence and the in-order sequence, respectively, and $n$ represents the number of nodes. The return value of the function is the binary tree constructed with $preorder[i..i+n-1]$ as the pre-order sequence and $inorder[j..j+n-1]$ as the in-order sequence.
4646

47-
> Preorder traversal: traverse the root node first, then traverse the left and right subtrees; Inorder traversal: traverse the left subtree first, then traverse the root node, and finally traverse the right subtree.
47+
The execution process of the function $dfs(i, j, n)$ is as follows:
4848

49-
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree.
49+
- If $n \leq 0$, it means there are no nodes, return a null node.
50+
- Take out the first node $v = preorder[i]$ of the pre-order sequence as the root node, and then use the hash table $d$ to find the position $k$ of the root node in the in-order sequence. Then the number of nodes in the left subtree is $k - j$, and the number of nodes in the right subtree is $n - k + j - 1$.
51+
- Recursively construct the left subtree $l = dfs(i + 1, j, k - j)$ and the right subtree $r = dfs(i + 1 + k - j, k + 1, n - k + j - 1)$.
52+
- Finally, return the binary tree with $v$ as the root node and $l$ and $r$ as the left and right subtrees, respectively.
5053

51-
If the node values given in the problem have duplicates, then we only need to record all the positions where each node value appears, and then recursively construct the tree.
54+
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree.
5255

5356
<!-- tabs:start -->
5457

@@ -61,7 +64,7 @@ If the node values given in the problem have duplicates, then we only need to re
6164
# self.right = right
6265
class Solution:
6366
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
64-
def dfs(i: int, j: int, n: int):
67+
def dfs(i: int, j: int, n: int) -> Optional[TreeNode]:
6568
if n <= 0:
6669
return None
6770
v = preorder[i]
@@ -304,7 +307,7 @@ var buildTree = function (preorder, inorder) {
304307

305308
<!-- tabs:end -->
306309

307-
### Solution 2
310+
If the node values given in the problem have duplicates, then we only need to record all the positions where each node value appears, and then recursively construct the tree.
308311

309312
<!-- tabs:start -->
310313

solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/Solution.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# self.right = right
77
class Solution:
88
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
9-
def dfs(i: int, j: int, n: int):
9+
def dfs(i: int, j: int, n: int) -> Optional[TreeNode]:
1010
if n <= 0:
1111
return None
1212
v = preorder[i]

solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README.md

+94-94
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,15 @@
4040

4141
## 解法
4242

43-
### 方法一:递归
43+
### 方法一:哈希表 + 递归
4444

45-
思路同 [105. 从前序与中序遍历序列构造二叉树](https://github.com/doocs/leetcode/blob/main/solution/0100-0199/0105.Construct%20Binary%20Tree%20from%20Preorder%20and%20Inorder%20Traversal/README.md)
45+
后序遍历的最后一个节点是根节点,我们可以根据这个特点找到根节点在中序遍历中的位置,然后递归地构造左右子树。
46+
47+
具体地,我们先用一个哈希表 $d$ 存储中序遍历中每个节点的位置。然后我们设计一个递归函数 $dfs(i, j, n)$,其中 $i$ 和 $j$ 分别表示中序遍历和后序遍历的起点,而 $n$ 表示子树包含的节点数。函数的逻辑如下:
48+
49+
- 如果 $n \leq 0$,说明子树为空,返回空节点。
50+
- 否则,取出后序遍历的最后一个节点 $v$,然后我们在哈希表 $d$ 中找到 $v$ 在中序遍历中的位置,设为 $k$。那么左子树包含的节点数为 $k - i$,右子树包含的节点数为 $n - k + i - 1$。
51+
- 递归构造左子树 $dfs(i, j, k - i)$ 和右子树 $dfs(k + 1, j + k - i, n - k + i - 1)$,并连接到根节点上,最后返回根节点。
4652

4753
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。
4854

@@ -56,15 +62,18 @@
5662
# self.left = left
5763
# self.right = right
5864
class Solution:
59-
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
60-
if not postorder:
61-
return None
62-
v = postorder[-1]
63-
root = TreeNode(val=v)
64-
i = inorder.index(v)
65-
root.left = self.buildTree(inorder[:i], postorder[:i])
66-
root.right = self.buildTree(inorder[i + 1 :], postorder[i:-1])
67-
return root
65+
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
66+
def dfs(i: int, j: int, n: int) -> Optional[TreeNode]:
67+
if n <= 0:
68+
return None
69+
v = postorder[j + n - 1]
70+
k = d[v]
71+
l = dfs(i, j, k - i)
72+
r = dfs(k + 1, j + k - i, n - k + i - 1)
73+
return TreeNode(v, l, r)
74+
75+
d = {v: i for i, v in enumerate(inorder)}
76+
return dfs(0, 0, len(inorder))
6877
```
6978

7079
```java
@@ -84,25 +93,29 @@ class Solution:
8493
* }
8594
*/
8695
class Solution {
87-
private Map<Integer, Integer> indexes = new HashMap<>();
96+
private Map<Integer, Integer> d = new HashMap<>();
97+
private int[] inorder;
98+
private int[] postorder;
8899

89100
public TreeNode buildTree(int[] inorder, int[] postorder) {
90-
for (int i = 0; i < inorder.length; ++i) {
91-
indexes.put(inorder[i], i);
101+
this.inorder = inorder;
102+
this.postorder = postorder;
103+
int n = inorder.length;
104+
for (int i = 0; i < n; ++i) {
105+
d.put(inorder[i], i);
92106
}
93-
return dfs(inorder, postorder, 0, 0, inorder.length);
107+
return dfs(0, 0, n);
94108
}
95109

96-
private TreeNode dfs(int[] inorder, int[] postorder, int i, int j, int n) {
110+
private TreeNode dfs(int i, int j, int n) {
97111
if (n <= 0) {
98112
return null;
99113
}
100114
int v = postorder[j + n - 1];
101-
int k = indexes.get(v);
102-
TreeNode root = new TreeNode(v);
103-
root.left = dfs(inorder, postorder, i, j, k - i);
104-
root.right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1);
105-
return root;
115+
int k = d.get(v);
116+
TreeNode l = dfs(i, j, k - i);
117+
TreeNode r = dfs(k + 1, j + k - i, n - k + i - 1);
118+
return new TreeNode(v, l, r);
106119
}
107120
}
108121
```
@@ -121,21 +134,23 @@ class Solution {
121134
*/
122135
class Solution {
123136
public:
124-
unordered_map<int, int> indexes;
125-
126137
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
127-
for (int i = 0; i < inorder.size(); ++i) indexes[inorder[i]] = i;
128-
return dfs(inorder, postorder, 0, 0, inorder.size());
129-
}
130-
131-
TreeNode* dfs(vector<int>& inorder, vector<int>& postorder, int i, int j, int n) {
132-
if (n <= 0) return nullptr;
133-
int v = postorder[j + n - 1];
134-
int k = indexes[v];
135-
TreeNode* root = new TreeNode(v);
136-
root->left = dfs(inorder, postorder, i, j, k - i);
137-
root->right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1);
138-
return root;
138+
unordered_map<int, int> d;
139+
int n = inorder.size();
140+
for (int i = 0; i < n; ++i) {
141+
d[inorder[i]] = i;
142+
}
143+
function<TreeNode*(int, int, int)> dfs = [&](int i, int j, int n) -> TreeNode* {
144+
if (n <= 0) {
145+
return nullptr;
146+
}
147+
int v = postorder[j + n - 1];
148+
int k = d[v];
149+
auto l = dfs(i, j, k - i);
150+
auto r = dfs(k + 1, j + k - i, n - k + i - 1);
151+
return new TreeNode(v, l, r);
152+
};
153+
return dfs(0, 0, n);
139154
}
140155
};
141156
```
@@ -150,21 +165,20 @@ public:
150165
* }
151166
*/
152167
func buildTree(inorder []int, postorder []int) *TreeNode {
153-
indexes := make(map[int]int)
168+
d := map[int]int{}
154169
for i, v := range inorder {
155-
indexes[v] = i
170+
d[v] = i
156171
}
157172
var dfs func(i, j, n int) *TreeNode
158173
dfs = func(i, j, n int) *TreeNode {
159174
if n <= 0 {
160175
return nil
161176
}
162177
v := postorder[j+n-1]
163-
k := indexes[v]
164-
root := &TreeNode{Val: v}
165-
root.Left = dfs(i, j, k-i)
166-
root.Right = dfs(k+1, j+k-i, n-k+i-1)
167-
return root
178+
k := d[v]
179+
l := dfs(i, j, k-i)
180+
r := dfs(k+1, j+k-i, n-k+i-1)
181+
return &TreeNode{v, l, r}
168182
}
169183
return dfs(0, 0, len(inorder))
170184
}
@@ -186,17 +200,22 @@ func buildTree(inorder []int, postorder []int) *TreeNode {
186200
*/
187201

188202
function buildTree(inorder: number[], postorder: number[]): TreeNode | null {
189-
const n = postorder.length;
190-
if (n == 0) {
191-
return null;
203+
const n = inorder.length;
204+
const d: Record<number, number> = {};
205+
for (let i = 0; i < n; i++) {
206+
d[inorder[i]] = i;
192207
}
193-
const val = postorder[n - 1];
194-
const index = inorder.indexOf(val);
195-
return new TreeNode(
196-
val,
197-
buildTree(inorder.slice(0, index), postorder.slice(0, index)),
198-
buildTree(inorder.slice(index + 1), postorder.slice(index, n - 1)),
199-
);
208+
const dfs = (i: number, j: number, n: number): TreeNode | null => {
209+
if (n <= 0) {
210+
return null;
211+
}
212+
const v = postorder[j + n - 1];
213+
const k = d[v];
214+
const l = dfs(i, j, k - i);
215+
const r = dfs(k + 1, j + k - i, n - 1 - (k - i));
216+
return new TreeNode(v, l, r);
217+
};
218+
return dfs(0, 0, n);
200219
}
201220
```
202221

@@ -221,51 +240,32 @@ function buildTree(inorder: number[], postorder: number[]): TreeNode | null {
221240
// }
222241
use std::rc::Rc;
223242
use std::cell::RefCell;
243+
use std::collections::HashMap;
224244
impl Solution {
225-
fn reset(
226-
inorder: &Vec<i32>,
227-
i_left: usize,
228-
i_right: usize,
229-
postorder: &Vec<i32>,
230-
p_left: usize,
231-
p_right: usize
232-
) -> Option<Rc<RefCell<TreeNode>>> {
233-
if i_left == i_right {
234-
return None;
235-
}
236-
let val = postorder[p_right - 1];
237-
let index = inorder
238-
.iter()
239-
.position(|&v| v == val)
240-
.unwrap();
241-
Some(
242-
Rc::new(
243-
RefCell::new(TreeNode {
244-
val,
245-
left: Self::reset(
246-
inorder,
247-
i_left,
248-
index,
249-
postorder,
250-
p_left,
251-
p_left + index - i_left
252-
),
253-
right: Self::reset(
254-
inorder,
255-
index + 1,
256-
i_right,
257-
postorder,
258-
p_left + index - i_left,
259-
p_right - 1
260-
),
261-
})
262-
)
263-
)
264-
}
265-
266245
pub fn build_tree(inorder: Vec<i32>, postorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> {
267246
let n = inorder.len();
268-
Self::reset(&inorder, 0, n, &postorder, 0, n)
247+
let mut d: HashMap<i32, usize> = HashMap::new();
248+
for i in 0..n {
249+
d.insert(inorder[i], i);
250+
}
251+
fn dfs(
252+
inorder: &[i32],
253+
postorder: &[i32],
254+
d: &HashMap<i32, usize>,
255+
i: usize,
256+
j: usize,
257+
n: usize
258+
) -> Option<Rc<RefCell<TreeNode>>> {
259+
if n <= 0 {
260+
return None;
261+
}
262+
let v = postorder[j + n - 1];
263+
let k = *d.get(&v).unwrap();
264+
let l = dfs(inorder, postorder, d, i, j, k - i);
265+
let r = dfs(inorder, postorder, d, k + 1, j + k - i, n - 1 - (k - i));
266+
Some(Rc::new(RefCell::new(TreeNode { val: v, left: l, right: r })))
267+
}
268+
dfs(&inorder, &postorder, &d, 0, 0, n)
269269
}
270270
}
271271
```

0 commit comments

Comments
 (0)