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

标签(空格分隔): LeetCode


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

题目链接
参考博文

表示根本不知道什么是卡特兰数,百度的截图
动态规划专题之---- Unique Binary Search Trees_第1张图片

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

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;j1];
 }

模拟一下输入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的时候
动态规划专题之---- Unique Binary Search Trees_第2张图片

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;j1];
            }
        }
        return dp[n];
    }

}

动态规划专题之---- Unique Binary Search Trees_第3张图片

你可能感兴趣的:(算法(leetcode实战))