Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
lucifer committed Jan 20, 2020
1 parent b88256f commit 6d4fd99
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [0091.decode-ways](./problems/91.decode-ways.md)
- [0092.reverse-linked-list-ii](./problems/92.reverse-linked-list-ii.md)
- [0094.binary-tree-inorder-traversal](./problems/94.binary-tree-inorder-traversal.md)
- [0095.unique-binary-search-trees-ii](./problems/95.unique-binary-search-trees-ii.md) 🆕
- [0096.unique-binary-search-trees](./problems/96.unique-binary-search-trees.md) 🆕

95.unique-binary-search-trees-ii

- [0098.validate-binary-search-tree](./problems/98.validate-binary-search-tree.md)
- [0102.binary-tree-level-order-traversal](./problems/102.binary-tree-level-order-traversal.md)
- [0103.binary-tree-zigzag-level-order-traversal](./problems/103.binary-tree-zigzag-level-order-traversal.md)
Expand Down
78 changes: 78 additions & 0 deletions problems/95.unique-binary-search-trees-ii.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
## 题目地址(95. 不同的二叉搜索树 II)

https://leetcode-cn.com/problems/unique-binary-search-trees-ii/description/

## 题目描述

```
给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树。
示例:
输入: 3
输出:
[
  [1,null,3,2],
  [3,2,null,1],
  [3,1,null,null,2],
  [2,1,3],
  [1,null,2,null,3]
]
解释:
以上的输出对应以下 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
```

## 思路

这是一个经典的使用分治思路的题目。基本思路和[96.unique-binary-search-trees](./96.unique-binary-search-trees.md)一样。

只是我们需要求解的不仅仅是数字,而是要求解所有的组合。我们假设问题 f(1, n) 是求解 1 到 n(两端包含)的所有二叉树。那么我们的目标就是求解 f(1, n)。

我们将问题进一步划分为子问题,假如左侧和右侧的树分别求好了,我们是不是只要运用组合的原理,将左右两者进行做和就好了,我们需要两层循环来完成这个过程。

## 关键点解析

- 分治法

## 代码

- 语言支持:Python3

Python3 Code:

```Python
class Solution:
def generateTrees(self, n: int) -> List[TreeNode]:
if not n:
return []

def generateTree(start, end):
if start > end:
return [None]
res = []
for i in range(start, end + 1):
ls = generateTree(start, i - 1)
rs = generateTree(i + 1, end)
for l in ls:
for r in rs:
node = TreeNode(i)
node.left = l
node.right = r
res.append(node)

return res

return generateTree(1, n)
```

## 相关题目

- [96.unique-binary-search-trees](./96.unique-binary-search-trees.md)
84 changes: 84 additions & 0 deletions problems/96.unique-binary-search-trees.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## 题目地址(96. 不同的二叉搜索树)

https://leetcode-cn.com/problems/unique-binary-search-trees-ii/description/

## 题目描述

```
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
示例:
输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
```

## 思路

这是一个经典的使用分治思路的题目。

对于数字 n ,我们可以 1- n 这样的离散整数分成左右两部分。我们不妨设其分别为 A 和 B。那么问题转化为 A 和 B 所能组成的 BST 的数量的笛卡尔积。而对于 A 和 B 以及原问题除了规模,没有不同,这不就是分治思路么?止于此,我们只需要考虑边界即可,边界很简单就是 n 小于等于 1 的时候,我们返回 1。

具体来说:

- 生成一个[1:n + 1] 的数组
- 我们遍历一次数组,对于每一个数组项,我们执行以下逻辑
- 对于每一项,我们都假设其是断点。断点左侧的是 A,断点右侧的是 B。
- 那么 A 就是 i - 1 个数, 那么 B 就是 n - i 个数
- 我们递归,并将 A 和 B 的结果相乘即可。

> 其实我们发现,题目的答案只和 n 有关,和具体 n 个数的具体组成,只要是有序数组即可。
题目没有明确 n 的取值范围,我们试一下暴力递归。

代码(Python3):

```python
class Solution:
def numTrees(self, n: int) -> int:
if n <= 1:
return 1
res = 0
for i in range(1, n + 1):
res += self.numTrees(i - 1) * self.numTrees(n - i)
return res
```

上面的代码会超时,并没有栈溢出,因此我们考虑使用 hashmap 来优化,代码见下方代码区。

## 关键点解析

- 分治法
- 笛卡尔积
- 记忆化递归

## 代码

- 语言支持:Python3

Python3 Code:

```Python
class Solution:
visited = dict()

def numTrees(self, n: int) -> int:
if n in self.visited:
return self.visited.get(n)
if n <= 1:
return 1
res = 0
for i in range(1, n + 1):
res += self.numTrees(i - 1) * self.numTrees(n - i)
self.visited[n] = res
return res
```

0 comments on commit 6d4fd99

Please sign in to comment.