96、不同的二叉搜索树
给你一个整数 n
,求恰由 n
个节点组成且节点值从 1
到 n
互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例1:
输入:n = 3
输出:5
示例2:
输入:n = 1
输出:1
思路:
一个树是由左子树 + 根节点 + 右子树构成,那么这道题就可以分解为从1~n每个节点作为根节点的二叉树总数之和,那么也就是需要知道如果以某一个节点为根,那么它的搜索树的种树是多少。
假设我们取第i个结点作为根节点,那么左侧就应该又i-1个结点,右侧有n-i个结点,那么我们可以假设i个结点构成的子树种树为G(i)
那么取第i个结点作为根节点的种树,应该是左子树的数目 * 右子树的数目
即
G
(
i
−
1
)
∗
G
(
n
−
i
)
G(i-1) * G(n-i)
G(i−1)∗G(n−i)
那么对于n个几点的种树
G
(
n
)
=
G
(
0
)
∗
G
(
n
−
1
)
+
.
.
.
+
G
(
i
−
1
)
∗
G
(
n
−
i
)
+
.
.
.
+
G
(
n
−
1
)
∗
G
(
0
)
G(n) = G(0) * G(n-1) + ... + G(i-1) * G(n-i) + ... + G(n-1) * G(0)
G(n)=G(0)∗G(n−1)+...+G(i−1)∗G(n−i)+...+G(n−1)∗G(0)
此时我们只需要迭代计算出G(0)到G(n-1)的值即可,该公式也叫卡特兰数
代码:
class Solution:
def numTrees(self, n: int) -> int:
G = [0] * (n + 1)
G[0] = 1
G[1] = 1
for i in range(2, n + 1):
for j in range(1, i + 1):
G[i] += G[j - 1] * G[ i - j]
return G[n]
95、不同的二叉搜索树2
给你一个整数 n
,请你生成并返回所有由 n
个节点组成且节点值从 1
到 n
互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。
示例1:
输入:n = 3
输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
示例2:
输入:n = 1
输出:[[1]]
思路:
这道题可以用回溯的方法来做,我们可以不同的以从1到n之间每个节点都作为顶点的情况,然后拼接左子树和右子树就行
class Solution:
def generateTrees(self, n: int) -> List[TreeNode]:
# 这里也可以做一下缓存,避免重复计算
# cache = {}
def generage(start, end):
# 这里如果根节点没有左子节点,或者没有右子结点,则返回包含一个空节点的数组
if start > end: return [None]
trees = []
# 遍历,使每个结点都作为根节点的情况
for i in range(start, end+1):
# 得到左子树和右子树的可能情况
left_trees = generage(start, i-1)
# 使用缓存情况下
# if (start, i-1) in cache:
# left_trees = cache[(start, i-1)]
# else:
# left_trees = generage(start, i-1)
# cache[(start, i-1)] = left_trees
right_trees = generage(i+1, end)
# 遍历左右子树笛卡尔积
for l in left_trees:
for r in right_trees:
cur_tree = TreeNode(i)
cur_tree.left = l
cur_tree.right = r
trees.append(cur_tree)
return trees
if not n: return []
return generage(1, n)