Skip to content

Commit 723452d

Browse files
committed
feat: add solutions to lcof problem: No.07
1 parent 52597c1 commit 723452d

File tree

9 files changed

+211
-151
lines changed

9 files changed

+211
-151
lines changed

lcof/面试题06. 从尾到头打印链表/README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,8 @@ class Solution {
8686
stk.push(head.val);
8787
}
8888
int[] ans = new int[stk.size()];
89-
int i = 0;
90-
while (!stk.isEmpty()) {
91-
ans[i++] = stk.pop();
89+
for (int i = 0; !stk.isEmpty(); ++i) {
90+
ans[i] = stk.pop();
9291
}
9392
return ans;
9493
}

lcof/面试题06. 从尾到头打印链表/Solution.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ public int[] reversePrint(ListNode head) {
1313
stk.push(head.val);
1414
}
1515
int[] ans = new int[stk.size()];
16-
int i = 0;
17-
while (!stk.isEmpty()) {
18-
ans[i++] = stk.pop();
16+
for (int i = 0; !stk.isEmpty(); ++i) {
17+
ans[i] = stk.pop();
1918
}
2019
return ans;
2120
}

lcof/面试题07. 重建二叉树/README.md

+119-86
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,19 @@
3434

3535
## 解法
3636

37-
前序序列的第一个结点 `preorder[0]` 为根节点,我们在中序序列中找到根节点的位置 `i`,可以将中序序列划分为左子树 `inorder[:i]` 和右子树 `inorder[i + 1:]`
37+
**方法一:哈希表 + 递归**
3838

39-
通过左右子树的区间,可以计算出左、右子树节点的个数,假设为 m、n。然后在前序节点中,从根节点往后的 m 个节点为左子树,再往后的 n 个节点为右子树
39+
由于我们每一次都需要在中序序列中找到根节点的位置,因此我们可以使用哈希表 $d$ 来存储中序序列的值和索引,这样可以将查找的时间复杂度降低到 $O(1)$
4040

41-
递归求解即可
41+
接下来,我们设计一个递归函数 $dfs(i, j, n)$,表示在前序序列中,从第 $i$ 个节点开始的 $n$ 个节点,对应的中序序列中,从第 $j$ 个节点开始的 $n$ 个节点,构造出的二叉树
4242

43-
> 前序遍历:先遍历根节点,再遍历左子树,最后遍历右子树;
44-
>
45-
> 中序遍历:先遍历左子树,再遍历根节点,最后遍历右子树。
43+
函数 $dfs(i, j, n)$ 的执行过程如下:
44+
45+
如果 $n = 0$,说明已经没有节点了,返回 $null$;
46+
47+
否则,我们取前序序列的第 $i$ 个节点作为根节点,创建一个树节点,即 `root = new TreeNode(preorder[i])`,然后我们在中序序列中找到根节点的位置,记为 $k$,则根节点左边的 $k - j$ 个节点为左子树,右边的 $n - k + j - 1$ 个节点为右子树。递归地调用函数 $dfs(i + 1, j, k - j)$ 构造左子树,调用函数 $dfs(i + k - j + 1, k + 1, n - k + j - 1)$ 构造右子树。最后返回根节点 `root`
48+
49+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。
4650

4751
<!-- tabs:start -->
4852

@@ -59,14 +63,18 @@
5963

6064
class Solution:
6165
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
62-
if not preorder:
63-
return None
64-
v = preorder[0]
65-
root = TreeNode(val=v)
66-
i = inorder.index(v)
67-
root.left = self.buildTree(preorder[1 : 1 + i], inorder[:i])
68-
root.right = self.buildTree(preorder[1 + i :], inorder[i + 1 :])
69-
return root
66+
def dfs(i, j, n):
67+
if n < 1:
68+
return None
69+
root = TreeNode(preorder[i])
70+
k = d[preorder[i]]
71+
l = k - j
72+
root.left = dfs(i + 1, j, l)
73+
root.right = dfs(i + 1 + l, k + 1, n - l - 1)
74+
return root
75+
76+
d = {v: i for i, v in enumerate(inorder)}
77+
return dfs(0, 0, len(preorder))
7078
```
7179

7280
### **Java**
@@ -82,52 +90,67 @@ class Solution:
8290
* }
8391
*/
8492
class Solution {
85-
private Map<Integer, Integer> indexes = new HashMap<>();
93+
private Map<Integer, Integer> d = new HashMap<>();
94+
private int[] preorder;
95+
private int[] inorder;
8696

8797
public TreeNode buildTree(int[] preorder, int[] inorder) {
88-
for (int i = 0; i < inorder.length; ++i) {
89-
indexes.put(inorder[i], i);
98+
int n = inorder.length;
99+
for (int i = 0; i < n; ++i) {
100+
d.put(inorder[i], i);
90101
}
91-
return dfs(preorder, inorder, 0, 0, preorder.length);
102+
this.preorder = preorder;
103+
this.inorder = inorder;
104+
return dfs(0, 0, n);
92105
}
93106

94-
private TreeNode dfs(int[] preorder, int[] inorder, int i, int j, int n) {
95-
if (n <= 0) {
107+
private TreeNode dfs(int i, int j, int n) {
108+
if (n < 1) {
96109
return null;
97110
}
98-
int v = preorder[i];
99-
int k = indexes.get(v);
100-
TreeNode root = new TreeNode(v);
101-
root.left = dfs(preorder, inorder, i + 1, j, k - j);
102-
root.right = dfs(preorder, inorder, i + 1 + k - j, k + 1, n - k + j - 1);
111+
int k = d.get(preorder[i]);
112+
int l = k - j;
113+
TreeNode root = new TreeNode(preorder[i]);
114+
root.left = dfs(i + 1, j, l);
115+
root.right = dfs(i + 1 + l, k + 1, n - l - 1);
103116
return root;
104117
}
105118
}
106119
```
107120

108-
### **JavaScript**
121+
### **C++**
109122

110-
```js
123+
```cpp
111124
/**
112125
* Definition for a binary tree node.
113-
* function TreeNode(val) {
114-
* this.val = val;
115-
* this.left = this.right = null;
116-
* }
117-
*/
118-
/**
119-
* @param {number[]} preorder
120-
* @param {number[]} inorder
121-
* @return {TreeNode}
126+
* struct TreeNode {
127+
* int val;
128+
* TreeNode *left;
129+
* TreeNode *right;
130+
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
131+
* };
122132
*/
123-
var buildTree = function (preorder, inorder) {
124-
if (preorder.length == 0) return null;
125-
const v = preorder[0];
126-
const root = new TreeNode(v);
127-
const i = inorder.indexOf(v);
128-
root.left = buildTree(preorder.slice(1, 1 + i), inorder.slice(0, i));
129-
root.right = buildTree(preorder.slice(1 + i), inorder.slice(1 + i));
130-
return root;
133+
class Solution {
134+
public:
135+
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
136+
unordered_map<int, int> d;
137+
int n = inorder.size();
138+
for (int i = 0; i < n; ++i) {
139+
d[inorder[i]] = i;
140+
}
141+
function<TreeNode*(int, int, int)> dfs = [&](int i, int j, int n) -> TreeNode* {
142+
if (n < 1) {
143+
return nullptr;
144+
}
145+
int k = d[preorder[i]];
146+
int l = k - j;
147+
TreeNode* root = new TreeNode(preorder[i]);
148+
root->left = dfs(i + 1, j, l);
149+
root->right = dfs(i + 1 + l, k + 1, n - l - 1);
150+
return root;
151+
};
152+
return dfs(0, 0, n);
153+
}
131154
};
132155
```
133156
@@ -143,56 +166,59 @@ var buildTree = function (preorder, inorder) {
143166
* }
144167
*/
145168
func buildTree(preorder []int, inorder []int) *TreeNode {
146-
indexes := make(map[int]int)
169+
d := map[int]int{}
147170
for i, v := range inorder {
148-
indexes[v] = i
171+
d[v] = i
149172
}
150173
var dfs func(i, j, n int) *TreeNode
151174
dfs = func(i, j, n int) *TreeNode {
152-
if n <= 0 {
175+
if n < 1 {
153176
return nil
154177
}
155-
v := preorder[i]
156-
k := indexes[v]
157-
root := &TreeNode{Val: v}
158-
root.Left = dfs(i+1, j, k-j)
159-
root.Right = dfs(i+1+k-j, k+1, n-k+j-1)
178+
k := d[preorder[i]]
179+
l := k - j
180+
root := &TreeNode{Val: preorder[i]}
181+
root.Left = dfs(i+1, j, l)
182+
root.Right = dfs(i+1+l, k+1, n-l-1)
160183
return root
161184
}
162185
return dfs(0, 0, len(inorder))
163186
}
164187
```
165188

166-
### **C++**
189+
### **JavaScript**
167190

168-
```cpp
191+
```js
169192
/**
170193
* Definition for a binary tree node.
171-
* struct TreeNode {
172-
* int val;
173-
* TreeNode *left;
174-
* TreeNode *right;
175-
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
176-
* };
194+
* function TreeNode(val) {
195+
* this.val = val;
196+
* this.left = this.right = null;
197+
* }
177198
*/
178-
class Solution {
179-
public:
180-
unordered_map<int, int> indexes;
181-
182-
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
183-
for (int i = 0; i < inorder.size(); ++i) indexes[inorder[i]] = i;
184-
return dfs(preorder, inorder, 0, 0, inorder.size());
199+
/**
200+
* @param {number[]} preorder
201+
* @param {number[]} inorder
202+
* @return {TreeNode}
203+
*/
204+
var buildTree = function (preorder, inorder) {
205+
const d = new Map();
206+
const n = inorder.length;
207+
for (let i = 0; i < n; ++i) {
208+
d.set(inorder[i], i);
185209
}
186-
187-
TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int i, int j, int n) {
188-
if (n <= 0) return nullptr;
189-
int v = preorder[i];
190-
int k = indexes[v];
191-
TreeNode* root = new TreeNode(v);
192-
root->left = dfs(preorder, inorder, i + 1, j, k - j);
193-
root->right = dfs(preorder, inorder, i + 1 + k - j, k + 1, n - k + j - 1);
210+
const dfs = (i, j, n) => {
211+
if (n < 1) {
212+
return null;
213+
}
214+
const k = d.get(preorder[i]);
215+
const l = k - j;
216+
const root = new TreeNode(preorder[i]);
217+
root.left = dfs(i + 1, j, l);
218+
root.right = dfs(i + 1 + l, k + 1, n - l - 1);
194219
return root;
195-
}
220+
};
221+
return dfs(0, 0, n);
196222
};
197223
```
198224

@@ -214,16 +240,23 @@ public:
214240
*/
215241

216242
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
217-
if (preorder.length == 0) return null;
218-
let val: number = preorder[0];
219-
let node: TreeNode = new TreeNode(val);
220-
let index: number = inorder.indexOf(val);
221-
node.left = buildTree(
222-
preorder.slice(1, index + 1),
223-
inorder.slice(0, index),
224-
);
225-
node.right = buildTree(preorder.slice(index + 1), inorder.slice(index + 1));
226-
return node;
243+
const d = new Map<number, number>();
244+
const n = inorder.length;
245+
for (let i = 0; i < n; ++i) {
246+
d.set(inorder[i], i);
247+
}
248+
const dfs = (i: number, j: number, n: number): TreeNode | null => {
249+
if (n < 1) {
250+
return null;
251+
}
252+
const k = d.get(preorder[i]) ?? 0;
253+
const l = k - j;
254+
const root = new TreeNode(preorder[i]);
255+
root.left = dfs(i + 1, j, l);
256+
root.right = dfs(i + 1 + l, k + 1, n - l - 1);
257+
return root;
258+
};
259+
return dfs(0, 0, n);
227260
}
228261
```
229262

lcof/面试题07. 重建二叉树/Solution.cpp

+17-14
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,23 @@
99
*/
1010
class Solution {
1111
public:
12-
unordered_map<int, int> indexes;
13-
1412
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
15-
for (int i = 0; i < inorder.size(); ++i) indexes[inorder[i]] = i;
16-
return dfs(preorder, inorder, 0, 0, inorder.size());
17-
}
18-
19-
TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int i, int j, int n) {
20-
if (n <= 0) return nullptr;
21-
int v = preorder[i];
22-
int k = indexes[v];
23-
TreeNode* root = new TreeNode(v);
24-
root->left = dfs(preorder, inorder, i + 1, j, k - j);
25-
root->right = dfs(preorder, inorder, i + 1 + k - j, k + 1, n - k + j - 1);
26-
return root;
13+
unordered_map<int, int> d;
14+
int n = inorder.size();
15+
for (int i = 0; i < n; ++i) {
16+
d[inorder[i]] = i;
17+
}
18+
function<TreeNode*(int, int, int)> dfs = [&](int i, int j, int n) -> TreeNode* {
19+
if (n < 1) {
20+
return nullptr;
21+
}
22+
int k = d[preorder[i]];
23+
int l = k - j;
24+
TreeNode* root = new TreeNode(preorder[i]);
25+
root->left = dfs(i + 1, j, l);
26+
root->right = dfs(i + 1 + l, k + 1, n - l - 1);
27+
return root;
28+
};
29+
return dfs(0, 0, n);
2730
}
2831
};

lcof/面试题07. 重建二叉树/Solution.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@
77
* }
88
*/
99
func buildTree(preorder []int, inorder []int) *TreeNode {
10-
indexes := make(map[int]int)
10+
d := map[int]int{}
1111
for i, v := range inorder {
12-
indexes[v] = i
12+
d[v] = i
1313
}
1414
var dfs func(i, j, n int) *TreeNode
1515
dfs = func(i, j, n int) *TreeNode {
16-
if n <= 0 {
16+
if n < 1 {
1717
return nil
1818
}
19-
v := preorder[i]
20-
k := indexes[v]
21-
root := &TreeNode{Val: v}
22-
root.Left = dfs(i+1, j, k-j)
23-
root.Right = dfs(i+1+k-j, k+1, n-k+j-1)
19+
k := d[preorder[i]]
20+
l := k - j
21+
root := &TreeNode{Val: preorder[i]}
22+
root.Left = dfs(i+1, j, l)
23+
root.Right = dfs(i+1+l, k+1, n-l-1)
2424
return root
2525
}
2626
return dfs(0, 0, len(inorder))

0 commit comments

Comments
 (0)