动态规划-不同的二叉搜索树
题目 给定一个整数n,求以1…n为节点组成的二叉搜索树有多少种?
输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
思路
-
给定一个1…n的序列,遍历给定的序列,假如遍历到i,一种1…(i-1) 作为左边子树,(i+1) 作为右边子树。之后可以采用递归的方式不断遍历左右两边的子树。
-
由于根节点都不同,所有每棵二叉树都是不一样的。
-
定义两个函数:
- G ( n ) G(n) G(n):长度为 n n n的序列的不同二叉树个数
- F ( i , n ) F(i,n) F(i,n):以i为根的不同二叉搜索树的个数( 1 < i < n 1 <i<n 1<i<n)
-
由于 G ( n ) G(n) G(n)是对遍历所有 i ( 1 n ) i (1~n) i(1 n)的 F ( i , n ) F(i,n) F(i,n)之和。即:
-
G ( n ) = ∑ i = 1 n F ( i , n ) G(n) =\sum_{i=1}^n{F(i,n)} G(n)=i=1∑nF(i,n)
-
G ( 0 ) = 1 G(0)=1 G(0)=1, G ( 1 ) = 1 G(1)=1 G(1)=1
-
F ( i , n ) = G ( i − 1 ) ∙ G ( n − i ) F(i,n) = G(i-1)\bullet G(n-i) F(i,n)=G(i−1)∙G(n−i)
-
由上可知:
G ( n ) = ∑ i = 1 n G ( i − 1 ) ∙ G ( n − i ) G(n) =\sum_{i=1}^n{G(i-1)\bullet G(n-i)} G(n)=i=1∑nG(i−1)∙G(n−i)
-
code
public class Solution{
public int numTrees(int n){
int[] G = new int[n+1];
G[0] = 1;
G[1] = 1;
for(int i = 2;i <= n; ++i){
for(int j = 1; j <= i;++j){
G[i] += G[j - 1] * G[i - j];
}
}
return G[n];
}
}