题意:输入n,节点值为1....n,构成的不同的bst(二叉查找树)共有多少个?
思路:n:节点个数, |left|表示左子树的节点个数,|rigth|表示右子树的节点个数,
递推关系:1、f(n) = sum(f(|left|*f|right|)(for root in 1,...,n, 从n个数中选择一个数作为根节点的值,剩余的数分别落在左右子树中))
2、对称性:当|left| = |right|时,f(left|) = f|right|),使用平移理论解释,Tree1(i->j),Tree2(i+x->j+x)对应的不同BST的种类是相同的, 推广,无论数字是否连续,只需树中的节点数目相同,BST的种类数相等。
3、使用带记忆的自顶向下算法/自底向上算法。
4、终止条件:f(0) = f(1) =1
带记忆的自顶向下算法
public int numTrees(int n) {
if(n == 0)
return 0;
int map[] = new int[n+1];
map[0] = 1;
map[1] = 1;
return updateMap(n, map);
}
public int updateMap(int n, int a[]){
if(a[n] != 0){
return a[n];
}
int sum = 0;
for(int i = 1; i < n + 1; i++){
sum += updateMap(i-1, a) * updateMap(n-i, a);
}
a[n] = sum;
return a[n];
}
public static void main(String[] args) {
Solution s = new Solution();
System.out.println(s.numTrees(0));
System.exit(0);
}自底向上算法
public int numTrees(int n) {
if(n == 0)
return 0;
int map[] = new int[n+1];
map[0] = 1;
map[1] = 1;
for(int i = 2; i <= n; i++){
for(int j = 1; j <= i; j++){
map[i] += map[j-1] * map[i-j];
}
}
return map[n];
}自底向上算法比带记忆的自顶向下算法快,因为递归耗时,同时问题需要用到全部的子问题空间。
本文介绍了一种计算由n个节点构成的不同二叉查找树(BST)数量的方法,通过递推公式f(n)=∑f(|left|)*f(|right|)进行求解,并探讨了自底向上算法与带记忆的自顶向下算法的实现细节。
472

被折叠的 条评论
为什么被折叠?



