力扣-96不同的二叉搜索树(dp)

力扣-96不同的二叉搜索树

1、题目

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数

示例 1:

img

输入:n = 3
输出:5

示例 2:

输入:n = 1
输出:1

2、分析

  1. 题目。求得是有多少种不同的二叉搜索树

  2. 方法。在二叉搜索树中,可以看出,每一部分其实都可以看出存在两个或者一个节点的简单二叉搜索树,所以,这题可以根据动态规划来进行设计求解。

    1个节点-->1种
    2个节点-->2种
    3个节点-->5种
    
    以2个节点来看,分别有2种情况:
    1、以1节点为头结点,此时左侧0,右侧1个节点
    2、以2节点为头结点,此时左侧1,右侧0
    故可以得出dp[2] = dp[0]*dp[1] + dp[1]*dp[0]
    
    我们以3个节点来看,分别有三种情况:
    1、以1节点为头结点,此时左侧0,右侧2个节点
    2、以2节点为头结点,此时左侧1,右侧1
    3、以3节点为头结点,此时左侧2,右侧0
    可以看出,这个是一个dp[0]*dp[2] + dp[1]*dp[1] + dp[2]*dp[0]的一个过程
    
    故可得我们的状态方程:dp[i] = dp[j-1]*dp[i-j]
    
  3. 初始值。由于我们使用了dp[0],根据dp[1]和dp[2]的值关系,我们可设定dp[0]值为1。

  4. 遍历。求n个节点的不同形状的搜索二叉树,我们采用的是动态规划,所以我们需要遍历1-n的所有子模块在这个过程中,左右侧的数量在进行变化,所以很明显,我们还需要加一层遍历,进行值累加。

  5. 推敲代码书写。

3、代码及注释

class Solution {
    
    
    public int numTrees(int n) {
    
    
        // 1.dp[i] 表示的是有i个节点时,亦或者当i这个节点为头结点的时候,总共的不同排列情况
        // 2.当选定i节点为头结点的时候,即子模块可分为左侧和右侧,两侧的排列方法也不一样,故选择乘积
        // 3.需要使用子模块,即采用动态规划进行求解,遍历1-n这个过程的子模块,左侧和右侧的数量在区间变化,故还需要一层循环进行调节,每一部分左侧右侧方式改变后可得新的值,所以应该是累加起来的dp[i]
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;

        for (int i = 2; i <= n; i++){
    
    
            for (int j = 1; j <= i; j++){
    
    
                // 4.左侧*右侧,例如i=3时,左侧最小为dp[0],最大为dp[2],然后每种左右侧情况进行值相乘后进行累加到当前dp[i]
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        
        return dp[n];
    }
}

4、练习

力扣题目链接:https://leetcode.cn/problems/unique-binary-search-trees/submissions/

猜你喜欢

转载自blog.csdn.net/qq_51326491/article/details/129262995
今日推荐