动态规划专题之---- Unique Binary Search Trees

来源:互联网 发布:网络剧小心超人与伽罗 编辑:程序博客网 时间:2024/06/06 01:05

标签(空格分隔): LeetCode


    • 分解子问题
    • 确定状态
    • 确定初始状态
    • 确定状态转移方程

题目链接
参考博文

表示根本不知道什么是卡特兰数,百度的截图
image_1bdeqri3b18kp29b1npl1btol759.png-13kB

根据动态规划解题步骤慢慢分析

1.分解子问题

根据题意分析,二叉搜索树不同原因在于。一个数列中的所有元素都可以成为祖先。
于是第一个子问题是每个数都可以作为祖先。我们可以遍历数列。

然后确定一个数为祖先后,剩下n-1个数先分为两拨,而这两拨如何分?左子树节点数从0开始一直到某个临界值时,这样过一遍就是完美了。

于是左子树的子树又可以根据这样的递推关系继续往下面分。

当祖先(根为数值为i时),左子树最大的数为i-1。于是左子树的元素个数可以从0增加到i-1。而右子树的节点个数也可以依次增多。

image_1bdescqft3uo1t8v60r8ad7e9.png-17.9kB

这里的n=3,不是说的根节点数字为3,而是说的当节点数为3的时候

2.确定状态

dp[i]=j 表示当有i的节点时,BST的种类数目。

3.确定初始状态

dp[0]=1; 没有节点只有一种情况,空树
dp[1]=dp[0]*dp[0]=1; 只有一个节点也是只有一种情况

4.确定状态转移方程

int i; for(int j=0;j<i;j++){    dp[i]+=dp[j]*dp[i-j-1]; }

模拟一下输入3的情况

i i=1 dp[1]=dp[0]dp[0] i=2 dp[2]=dp[1]dp[0] dp[2]=dp[0]dp[1] i=3 dp[3]=dp[2]dp[0] dp[3]=dp[1]dp[1] dp[3]=dp[0]dp[2]

1. i=1 表示只有一个节点的情况
2. i=2 表示两个节点的情况,这个时候就可以利用case1中计算出来的结果dp[1]了。
3. i=3 表示三个节点的情况,这个时候就可以利用case2中计算出来的结果了。

对应i=3的时候
image_1bdesri85133m1l1811i21tlp16rm.png-109.7kB

public class Solution{    public int numTrees(int n){        if(n==0||n==1){            return 1;        }        int []dp=new int[n+1];        //每个数都可以做根节点,相当于有这么多个节点时        for(int i=1;i<=n;i++){            //i为根节点时,左子树从0开始增加            for(int j=0;j<i;j++){                dp[i]+=dp[j]*dp[i-j-1];            }        }        return dp[n];    }}

image_1bdetejv91u6a1a6k3fo1vo2q9113.png-20.9kB

0 0
原创粉丝点击