力扣第九十六题-不同的二叉搜索树 前言 一、思路 二、实现

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

前言

力扣第九十六题 不同的二叉搜索树 如下所示:

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

示例 1:

1
2
ini复制代码输入: n = 3
输出: 5

一、思路

这一题比上一题不同的是:只关心二叉搜素树的种树,而不关系树的节点了

所以一开始我的思路也是用递归来做的,去除了保留路径的部分,仅得到左孩子的个数和右孩子的个数即可。7代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码public int dfs(int start, int end) {
int ret = 0;
if (start > end) {
return 1;
}
// 枚举可行根节点
for (int i = start; i <= end; i++) {
// 找到所有的左子树
int left = dfs(start, i - 1);

// 找到所有的右子树
int right = dfs(i + 1, end);
ret += left * right;
}
return ret;
}

但是很可惜,在 n=18 时会提示超出时间限制!

那既然不能用 递归 来自顶向下,那就只能使用 动态规划 来实现 自底向上 了。

首先我们先看一下 递归 中调用的地方,我们发现在递归中一直在求 1 ~ i-1i+1 ~ n 左孩子和右孩子个数。

我们不妨设 dp[i] 为长度为 i 的不同二叉搜索树的个数。

可以有 dp[n] = dp[0]dp[n-1] + dp[1]dp[n-2] + dp[2]dp[n-3] + ... + dp[n-1]dp[0]

公式解释:

因为 dp[n] 就是选择 1 ~ n 中的某一个元素 i 为根,再将 1 ~ i-1 中的元素作为左孩子, i+1 ~ n 中的元素作为右孩子。

dp[0]dp[n-1] 就表示选择了第一个元素作为根有多少种结果。

此外,因为二叉搜索树的特殊性。对于 1, 2, 31, 2, 4 组成的二叉搜索树的种数是相同的。所以我们在公式中可以忽略元素的值,而只关注元素的个数,因为相同元素个数组成的二叉搜索树的种树是相同的。

二、实现

实现代码

实现代码与思路中保持一致

1
2
3
4
5
6
7
8
9
10
java复制代码    public int numTrees(int n) {
int[] dp = new int[n +1];
dp[0] = dp[1] = 1; // 0个和1个元素都只有一种结果
for (int i=2; i<= n; i++) {
for (int j=1; j<=i; j++) {
dp[i] += dp[j-1] * dp[i-j];
}
}
return dp[n];
}

测试代码

1
2
3
4
java复制代码    public static void main(String[] args) {
int ret = new Number96().numTrees(3);
System.out.println(ret);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%