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 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‎

Lines changed: 2 additions & 3 deletions
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‎

Lines changed: 2 additions & 3 deletions
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‎

Lines changed: 119 additions & 86 deletions
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‎

Lines changed: 17 additions & 14 deletions
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‎

Lines changed: 8 additions & 8 deletions
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)

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