Skip to content

Commit 56ac0b1

Browse files
authored
Merge pull request doocs#155 from biubiubiubiubiubiubiu/master
add solution 1008
2 parents b140fa7 + 046b2bb commit 56ac0b1

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
## 先序遍历构造二叉树
2+
3+
### 问题描述
4+
5+
返回与给定先序遍历 **preorder** 相匹配的二叉搜索树(binary **search** tree)的根结点。
6+
7+
**示例1:**
8+
9+
```
10+
输入:[8,5,1,7,10,12]
11+
输出:[8,5,10,1,7,null,12]
12+
```
13+
14+
![示例1](/img/Construct-Binary-Search-Tree-from-Preorder-Traversal.png)
15+
16+
**提示:**
17+
18+
- `1 <= preorder.length <= 100`
19+
- The values of `preorder` are distinct.
20+
21+
### 解法
22+
23+
二叉树类的题目可以考虑使用递归中的分治法,让本次递归的根节点(sub-root)来管理自身子树的生成方式。而本题使用的是**前序遍历法**所生成的数组,则先检查了根节点,再检查左子树,再检查右子树。因此每层递归我们需要确定的是:
24+
25+
* 本层递归的根节点是什么?
26+
* 根节点确定后,本层递归之后的左子树范围是什么,右子树的范围是什么?
27+
28+
对于第一个问题,我们知道前序遍历法的根节点一定是当前范围内的第一个元素;而对于第二个问题,我们知道右子树开始于**第一个比当前根节点大的元素**,而左子树结束于该元素的前面一个元素。在解决了这两个问题后,答案已经比较明确了,在每一层递归中,我们需要一个 start 和一个 end 来表示当前的递归所涉及的元素范围:
29+
30+
* 确定当前的递归是否结束(start > end || start >= end)
31+
* 确定当前递归层的根节点(start)
32+
* 确定左子树的范围(start + 1, leftEnd - 1)和右子树的范围(leftEnd, end)
33+
34+
因此有如下的递归解法:
35+
36+
```java
37+
/**
38+
* Definition for a binary tree node.
39+
* public class TreeNode {
40+
* int val;
41+
* TreeNode left;
42+
* TreeNode right;
43+
* TreeNode(int x) { val = x; }
44+
* }
45+
*/
46+
class Solution {
47+
public TreeNode bstFromPreorder(int[] preorder) {
48+
if (preorder == null || preorder.length == 0) {
49+
return null;
50+
}
51+
// 进入分治法的递归
52+
return helper(preorder, 0, preorder.length - 1);
53+
}
54+
55+
private TreeNode helper(int[] preorder, int start, int end) {
56+
// System.out.println("start: " + start + " end: " + end);
57+
// 确认递归结束的标志,当 start == end 时,表示该区间只剩下一个 subRoot 节点
58+
if (start > end) {
59+
return null;
60+
}
61+
if (start == end) {
62+
return new TreeNode(preorder[start]);
63+
}
64+
// 前序遍历,首先遍历到的为根
65+
TreeNode root = new TreeNode(preorder[start]);
66+
int leftEnd = start;
67+
while (leftEnd <= end) {
68+
if (preorder[leftEnd] > preorder[start]) {
69+
break;
70+
}
71+
leftEnd++;
72+
}
73+
// System.out.println("leftEnd:" + leftEnd + " num: " + preorder[leftEnd]);
74+
root.left = helper(preorder, start + 1, leftEnd - 1);
75+
root.right = helper(preorder, leftEnd, end);
76+
return root;
77+
}
78+
}
79+
```
80+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* public class TreeNode {
4+
* int val;
5+
* TreeNode left;
6+
* TreeNode right;
7+
* TreeNode(int x) { val = x; }
8+
* }
9+
*/
10+
class Solution {
11+
public TreeNode bstFromPreorder(int[] preorder) {
12+
if (preorder == null || preorder.length == 0) {
13+
return null;
14+
}
15+
// 进入分治法的递归
16+
return helper(preorder, 0, preorder.length - 1);
17+
}
18+
19+
private TreeNode helper(int[] preorder, int start, int end) {
20+
// System.out.println("start: " + start + " end: " + end);
21+
// 确认递归结束的标志,当 start == end 时,表示该区间只剩下一个 subRoot 节点
22+
if (start > end) {
23+
return null;
24+
}
25+
if (start == end) {
26+
return new TreeNode(preorder[start]);
27+
}
28+
// 前序遍历,首先遍历到的为根
29+
TreeNode root = new TreeNode(preorder[start]);
30+
int leftEnd = start;
31+
while (leftEnd <= end) {
32+
if (preorder[leftEnd] > preorder[start]) {
33+
break;
34+
}
35+
leftEnd++;
36+
}
37+
// System.out.println("leftEnd:" + leftEnd + " num: " + preorder[leftEnd]);
38+
root.left = helper(preorder, start + 1, leftEnd - 1);
39+
root.right = helper(preorder, leftEnd, end);
40+
return root;
41+
}
42+
}

0 commit comments

Comments
 (0)