【leetcode】96. Unique Binary Search Trees

230 篇文章 0 订阅

96. 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

题目链接:https://leetcode.com/problems/unique-binary-search-trees/

 

解题抓瞎思路

对于这种递增的题目,很容易想到DP,关键在于DP表达式是怎么样的。

一般我做DP的思路是,从n=1开始,列出前几种n较小情况的解,再总结规律。

在本题中,

n=1,solution=1

n=2,solution=2

而题中给出了

n=3,solution=5

我尝试写出n=4的情况,发现在树结构上从n变为n+1时,新节点插入的方法:

1)向n下所有树向外延伸一条边插入,作为根节点或叶子节点。即对每个树结构有2种插入方式。

2)向n下所有树中间插入,作为非根节点、非叶子节点。这里的计算,因为BST的子数还是BST,所以可以根据前面已经算出的节点数对应的BST个数通过排列组合得到。

举个例子:

这是我直观感受总结的规律,但实际上还是复杂了一步,1)可合并入2)中。

接下来是正确的打开方式

 

正确解法

实际上正确的思路只需要2),1)是完全可以并入2)中的。

太久没做题了,忘记DP正确的打开方式,本题是将问题递归到子问题上去,这题就直接对子树出现的情况进行排列组合:

1)任意数字都可作为根节点。

2)根节点的左右子树各自是一个本题的子问题,两个子问题之间是组合关系(相乘关系)。

有了以上两点核心思路,写出表达式,这题就解完了。

dp[n] = dp[0] * dp[n-1] + dp[1] * dp[n-2] + ... 
      = sum(dp[i] * dp[n-i-1]) for 0<=i<=n-1

法一:循环计算

写循环实现。

代码:

class Solution {
public:
    int numTrees(int n) {
        int dp[n+1] = {0};
        dp[0] = 1;
        for (int i = 1; i<=n; ++i){
            for(int j = 0; j <= i-1; ++j){
                dp[i] += dp[j] * dp[i-j-1];
            }
        }
        return dp[n];
    }
};

法二:算出通项公式

进一步算出由表达式推倒出来的通项公式。

这个方法是查资料得到的,此题的计算结果正式卡塔兰数,由卡塔兰数的推倒公式得到通项式为C(2n, n)/(n+1),表示2n个数中任意取n个,再除以(n+1)。

为了防止相乘时整型移除,需要使用long。

代码:

class Solution {
public:
    int numTrees(int n) {
        long res = 1;
        for (int i = n + 1; i <= 2 * n; ++i) {
            res = res * i / (i - n);
        }
        return res / (n + 1);
    }
};

 

延伸学习

卡塔兰数

卡塔兰数和斐波那契数列一样,就是一种特殊的数列,具有一定的几何意义,常与实际问题相关,因此就有人去研究其更多性质。

如何理解卡塔兰数:

卡塔兰数简单印象:https://blog.csdn.net/wu_tongtong/article/details/78161211

 

维基百科更多性质,开始看不懂了:https://zh.wikipedia.org/zh-hans/%E5%8D%A1%E5%A1%94%E5%85%B0%E6%95%B0

 

todo

卡塔兰数的四种问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值