原题链接: https://leetcode.com/problems/unique-binary-search-trees/
1. 题目介绍
Given n, how many structurally unique BST’s (binary search trees) that store values 1 … n?
给出一个数n,求从1到n的所有数可以形成多少种不一样的二叉树?
Example:
2. 解题思路
动态规划
假设二叉树的根节点是 i (1 <= i <= n),以 i 为根节点的不同二叉树的总个数,就等于 i 的左子树的总个数乘以 i 的右子树的总个数。因此解题的关键在于求左子树和右子树的个数。
因为是二叉树,所以 i 的左子树中,肯定都是比 i 小的数。因此左子树会有 i-1 个节点,这些节点是从1 到 i-1 的数。于是求左子树个数的问题就转化为求1 ~ i-1的所有数可以形成多少种不一样的二叉树的问题。
同样的道理,i 的右子树中,肯定都是比 i 大的数。因此右子树会有 n-i 个节点,这些节点是从 i+1 到 n 的数。于是求右子树个数的问题就转化为求 i+1~n 的所有数可以形成多少种不一样的二叉树的问题。
使用一维数组 dp[],dp[i] 代表 1~i 个数形成的二叉树的个数。其中特别赋值dp[ 0 ] = 1,代表着空的二叉树也算一个树。
如果n = 1,那么只有一种二叉树,dp[ 1 ] = 1.
如果n = 2,1和2都可以作为根节点,有2种二叉树,dp[ 2 ] = 2;
这个2是怎么来的呢?
- 首先以 1 为根节点,左子树为空,右子树的节点总数为1,因此左子树总数乘以右子树总数,有dp[0] x dp[1] = 1
- 然后以 2 为根节点,左子树节点总数为1,右子树为空,因此左子树总数乘以右子树总数,有dp[1] x dp[2] = 1
- 然后以上两者相加,即为最后的dp[ 2 ] = 2
如果n = 3,dp[ 3 ] = 5
1 为根节点时,左子树为空,右子树的节点总数为2,因此左子树总数乘以右子树总数,有dp[0] x dp[2] = 2
2 为根节点时,左子树节点总数为1,右子树总数为1,因此左子树总数乘以右子树总数,有dp[1] x dp[1] = 1
3 为根节点时,左子树节点总数为2,右子树总数为0,因此左子树总数乘以右子树总数,有dp[2] x dp[0] = 2
以上1、2、3分别为根节点的结果相加后,得到了 n = 3时所有二叉树的种类为5。
通过上面的几个例子我们可以看出,可以使用动态规划的方法求节点数目为 n 的二叉树总数。
递推方程式为:
d
p
[
i
]
+
=
d
p
[
j
−
1
]
∗
d
p
[
i
−
j
]
dp[ i ] += dp[ j - 1] * dp[i - j]
dp[i]+=dp[j−1]∗dp[i−j]
其中 2<= i <= n, 1<= j <= i
实现代码
class Solution {
public int numTrees(int n) {
if( n == 0 ) {
return 0;
}
int ans = 0;
int [] dp = new int [n+1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2 ; i<=n ; i++) {
for(int j = 1 ; j<=i ; j++) {
dp[i] += dp[j-1] * dp[i-j];
}
}
return dp[n];
}
}