力扣-96不同的二叉搜索树
1、题目
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3
输出:5
示例 2:
输入:n = 1
输出: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]
-
初始值。由于我们使用了dp[0],根据dp[1]和dp[2]的值关系,我们可设定dp[0]值为1。
-
遍历。求n个节点的不同形状的搜索二叉树,我们采用的是动态规划,所以我们需要遍历1-n的所有子模块,在这个过程中,左右侧的数量在进行变化,所以很明显,我们还需要加一层遍历,进行值累加。
-
推敲代码书写。
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/