96. 不同的二叉搜索树
题目描述
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3
输出:5
示例 2:
输入:n = 1
输出:1
提示:
- 1 <= n <= 19
二叉搜索树
定义
二叉搜索树是一种节点值之间具有一定数量级次序的二叉树,对于树中每个节点:
- 若其左子树存在,则其左子树中每个节点的值都不大于该节点值;
- 若其右子树存在,则其右子树中每个节点的值都不小于该节点值。
示例:
一、动态规划
这种思想是比较容易的,如上图,我们可以把二叉树分为三部分:根节点、根节点的左子树、根节点的右子树,根节点分别是从1~n,左子树和右子树拥有的结点数是固定的,如n=3时,根节点为1时,无左子树,右子树有2、3;根节点为2时,左子树只有1,右子树只有3;根节点为3时,左子树有1、2,无右子树。
以 n = 3 为例:
- 根节点为1时,无左子树,右子树有2、3:二叉搜索树数量即为2、3的二叉搜索树数量,即n=2时二叉搜索树数量;
- 根节点为2时,左子树只有1,右子树只有3:二叉搜索树数量即为仅有1的二叉搜索树数量和仅有3的二叉搜索树数量相乘;
- 根节点为3时,左子树有1、2,无右子树:二叉搜索树数量即为1、2的二叉搜索树数量,即n=2时二叉搜索树数量;
- 将上述三种情况相加即为结果。
class Solution:
def numTrees(self, n: int) -> int:
if n == 1:
return 1
nums = [1, 1] # n个结点时二叉搜索树的数量,定义nums[0]=1, 显然nums[1]=1
for i in range(2, n+1): # i从2到n,为得到nums
tmp = 0
for j in range(1, i+1): # j从1到n,计算nums[i]
print(j)
tmp += nums[j-1]*nums[i-j]
nums.append(tmp)
return nums[n]
简单优化一下
class Solution:
def numTrees(self, n: int) -> int:
nums = [0 for i in range(n+1)]
nums[0] = nums[1] = 1
for i in range(2, n+1): # i从2到n,为得到nums
for j in range(1, i+1): # j从1到n,计算nums[i]
nums[i] += nums[j-1]*nums[i-j]
return nums[n]
二、卡特兰数
参考:「算法入门笔记」卡特兰数
这里直接给出递推公式:
C
1
=
1
,
C
n
=
4
n
−
2
n
+
1
C
n
−
1
C_1=1, C_n=\frac{4n-2}{n+1}C_{n-1}
C1=1,Cn=n+14n−2Cn−1