Leetcode96. Unique Binary Search Trees

题目:Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n?

Example:

Input: 3
Output: 5
Explanation:
Given n = 3, there are a total of 5 unique BST's:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

通过学习95题(https://blog.csdn.net/ytwang95/article/details/81624920)之后,我们已经对二叉搜索树有了一定的了解。这道题只需要计算结果树的个数。因此既可以考虑迭代的方式,也可以用动态规划。

思路一:迭代:

对于一个节点i,当其为根节点时,左子树的节点范围为[1,...i-1],右子树的节点范围为[i+1,...n]。对这个根节点来说,二叉树的个数为左子树的个数乘以右子树的个数。则从[1,n]选择根节点,递归计算其左右子树的个数,再将它们相乘,累加就是结果树的个数。

然而……事实证明……会超时……

代码如下:

class Solution {
public:
    int numTrees(int n) {
        if(n<=1)    return 1;
        int count=0;
        for(int i=1;i<=n;++i)
            count+=numTrees(i-1)*numTrees(n-i);
        return count;   
    }
};

思路二:动态规划

当n=1时  

1                                        (1种)

当n=2时 

1                                   2    (2种=[null,2]+[1,null])

    \                           /   

       2                    1

抽象为:

       root

   /            \

left            right  

n=3时

left (节点个数)right(节点个数)
02
11
2

0

 可以将问题看作是去一个节点做根节点,其余分为左右子树,考虑左右子树的可能个数,利用动态规划,用一个数组count[i]存储节点个数为i的树的可能个数,每次算新的结果会用到前面的结果。

n=3为例:

结果树的个数为:count[0]*count[2]+count[1]*count[1]+count[2]*count[0]                                      

看了大神们的博客发现这个叫做卡特兰数 。即:

代码如下:

class Solution {
public:
    int numTrees(int n) {
        if(n==0) return 0;
        int *count=new int[n+1];
	count[0]=1;
	count[1]=1;
	if(n==1) return 1;
	for(int i=2;i<=n;i++){
	    count[i]=0;
	    for(int j=1;j<=i>>1;j++) //尽量不重复计算的方法
	        count[i]+=count[j-1]*count[i-j]*2;
	    if(i&1!=0) count[i]+=count[i>>1]*count[i>>1];
        }
        /*
        for(int i=2;i<=n;i++){
	    count[i]=0;
	    for(int j=1;j<=i;j++)  //代码简洁的方法
	        count[i]+=count[j-1]*count[i-j];
	}
        */
	return count[n];
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值