Leetcode:96. 不同的二叉搜索树

Leetcode:96. 不同的二叉搜索树

Leetcode:96. 不同的二叉搜索树

题目在链接中,点进去看看吧!

先介绍一个名词:卡特兰数

卡特兰数

卡特兰数Cn满足以下递推关系:

[C_{n+1}=C_0C_n+C_1C_{n-1}+...+C_nC_0 ]

有兴趣的同学点击这里查看亚特兰数的百度百科

很巧的是,这道题可以利用亚特兰数计算出有多少个不同的BST。

Don't talk,show me code!

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

简单分析

这道题利用的是动态规划的思想,递推得出一个dp数组。在找规律的过程中,我们意外发现这道题的答案与亚特兰数的数学递推式dp方程完全一致!

前提条件:这是一颗BST树,中序遍历得出的排列等于其升序排列

  1. 首先,当结点数为0时,树的个数为1

  2. 分析当结点数为1时:

    1. 取1为根节点,则左子树的结点数为0,右子树的结点数为0
    2. 因此结点数为1的左右子树情况为(1*1=1)
  3. 分析当结点数为2时:

    1. 取1为根节点,则左子树的结点数为0,右子树的结点数为1
    2. 因此1根节点所有可能出现的树情况为(1*1=1)
    3. 取2为根节点,则左子树的结点数为1,右子树的结点数为0
    4. 因此2根节点所有可能出现的树情况为(1*1=1)
    5. 因此结点数为2的左右子树情况为(1+1=2)
  4. 分析当结点数为3时:

    1. 取1为根节点,则左子树的结点数为0,右子树的结点数为2
    2. 因此1根节点所有可能出现的树情况为(1*2=2)
    3. 取2为根节点,则左子树的结点数为1,右子树的结点数为1
    4. 因此2根节点所有可能出现的树情况为(1*1=1)
    5. 取2为根节点,则左子树的结点数为2,右子树的结点数为0
    6. 因此3根节点所有可能出现的树情况为(2*1=2)
    7. 因此结点数为3的左右子树情况为(1+2+1=5)
  5. 有兴趣可以继续递推,总之总结规律:

    [dp[k]=sum_0^{k-1} dp[i]*dp[k-i-1] ]

  6. 然后就是编程实现啦~

原文地址:https://www.cnblogs.com/cell-coder/p/12354623.html