LeetCode--96. 不同的二叉搜索树(动态规划)

不同的二叉搜索树(动态规划)

1. 题目描述

难度:中等
在这里插入图片描述

2. 题目分析

首先我们要知道二叉搜索树的特点:

  • 左子树肯定小于其根节点
  • 右子树肯定大于其根节点
  • 第一个根节点的值总是大于左边的所有的节点的值
  • 第一个根节点的值总是小于于右边的所有的节点的值

现在我们来看看怎么用动态规划来解决这个问题:

  • 动态规划
    动态规划的解决思路是从小问题开始,然后寻找动态转移方程,进而求解,我们来看看怎么得到动态转移方程的,以输入 n = 4 为例,节点的值分别是 nums = [1, 2, 3, 4]:
    • 当根节点的值为1时
      在这里插入图片描述
      这时左子树没有节点,右子树的节点有三个是 right = [2, 3, 4], 此时右子树的组合数与n=3时的组合数是等价的。 也就是说, right = [2, 3, 4] 与 [1, 2, 3]二者是等价的。所以,当根节点的值为1时,dp[root=1] = dp[n=3]
    • 当根节点的值为2时
      在这里插入图片描述
      这时左子树left = [1],右子树的节是 right = [3, 4], 此时左子树的组合数与n=1时的组合数是等价的,右子树的组合数与n=2时的组合数是等价的。 所以,当根节点的值为2时,dp[root=2] = dp[n=1] x dp[n=2]
    • 当根节点的值为3时
      在这里插入图片描述
      这时左子树left = [1, 2],右子树的节是 right = [4], 此时左子树的组合数与n=2时的组合数是等价的,右子树的组合数与n=1时的组合数是等价的。 所以,当根节点的值为3时,dp[root=3] = dp[n=2] x dp[n=1]
    • 当根节点的值为4时
      在这里插入图片描述
      这时左子树left = [1, 2, 3],右子树的节是 right = [], 此时左子树的组合数与n=3时的组合数是等价的。 所以,当根节点的值为2时,dp[root=2] = dp[n=3]
      综上所述,我们就能得到前i个节点的组合数:
dp[i] = dp[i] + dp[i-1]*dp[1] +dp[i-2]*dp[2] + ...+dp[1]*dp[i-1]+dp[i]

3. C语言实现

代码如下:

// 动态规划
int numTrees(int n){
    if(n == 0) return 0;
    int res;
    int* dp = (int *)malloc(sizeof(int)*(n+1));
    dp[0] = 1;
    for(int i = 1; i < n+1; i++) dp[i] = 0;
    for(int i = 1; i < n+1; i++){
        for(int j = 0; j < i; j++) 
            dp[i] += dp[j]*dp[i-j-1]; 
    }
    res = dp[n];
    free(dp);
    return res;
}

运行结果为:
在这里插入图片描述

4. Python实现

代码如下:

class Solution:
    def numTrees(self, n: int) -> int:
        if not n:
            return 0
        dp = []
        for i in range(n+1):
            dp.append(0) 
        dp[0] = 1
        for i in range(1, n+1):
            for j in range(i):
                dp[i] += dp[j]*dp[i-j-1]
        return dp[n]

运行结果为:
在这里插入图片描述

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页