LeetCode 96——不同的二叉搜索树
1. 题目

2. 解答
以 \(1, 2, \cdots, n\) 构建二叉搜索树,其中,任意数字都可以作为根节点来构建二叉搜索树。当我们将某一个数字作为根节点后,其左边数据将构建为左子树,右边数据将构建为右子树。因此,这是一个递归问题。
若以第 \(i\) 个数据为根节点,其左边数据有 \(i-1\) 个,左子树可能情况为 left_num,右边数据有 \(n-i\) 个,右子树可能情况为 right_num,因此以当前数据为根节点可以构建出 left_num * right_num 个二叉搜索树。
所以,我们要做的就是遍历 \(i = 1\cdots n\),统计出每个数据作为根节点可以构建出的二叉搜索树总个数即可。
- 递归法
class Solution {
public:
int numTrees(int n) {
int sum = 0;
if (n <= 1) return 1;
// 以当前的数为根节点,左右两边的数分别构建子树
for (int i = 1; i <= n; i++)
{
int left_num = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树
int right_num = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树
sum += left_num * right_num;
}
return sum;
}
};
但是上面的程序运行时超时了,其实我们只需要统计一半数据就可以了,因为两边是对称的。
比如我们有 1,2,3,4,5 五个数,以 2 作为根节点,左边有 1 个数,右边有 3 个数。以 4 作为根节点,左边有 3 个数,右边有 1 个数。这两种情况是一样的,因此如果数据个数为偶数,我们只需要统计一半数据即可,而为奇数的话我们就要再多统计一个中间数据。
class Solution {
public:
int numTrees(int n) {
int sum = 0;
if (n <= 1) return 1;
int is_odd = n % 2;
int mid = n / 2;
// 以当前的数为根节点,左右两边的数分别构建子树
for (int i = 1; i <= mid; i++)
{
int left_num = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树
int right_num = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树
sum += left_num * right_num;
}
sum = sum * 2;
if (is_odd) sum = sum + numTrees(mid) * numTrees(n - mid - 1);
return sum;
}
};
此外,我们还可以定义一个全局变量,来存放已经计算过的数值,避免在递归过程中大量地重复计算。
class Solution {
public:
#define MAX 1000
int nums[MAX]; // 存放已经计算过的数值
int numTrees(int n) {
int sum = 0;
//if (n <= 0) return 1;
if (n <= 1) return 1;
// 以当前的数为根节点,左右两边的数分别构建子树
for (int i = 1; i <= n; i++)
{
if (nums[i-1] == 0) nums[i-1] = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树
int left_num = nums[i-1];
if (nums[n-i] == 0) nums[n-i] = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树
int right_num = nums[n-i];
sum += left_num * right_num;
}
return sum;
}
};
- 迭代法
还可以将递归改写为循环,避免函数多次调用执行效率较低。
class Solution {
public:
int numTrees(int n) {
int nums[n+1] = {0};
nums[0] = 1;
nums[1] = 1;
if (n <= 1) return 1;
for (int i = 2; i <= n; i++)
{
// 从 n=2 开始统计可以构建多少个不同的二叉搜索树
for (int j = 1; j <= i; j++)
{
nums[i] += nums[j-1] * nums[i-j];
}
}
return nums[n];
}
};
获取更多精彩,请关注「seniusen」!

LeetCode 96——不同的二叉搜索树的更多相关文章
- Java实现 LeetCode 96 不同的二叉搜索树
96. 不同的二叉搜索树 给定一个整数 n,求以 1 - n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 ...
- Leetcode 96. 不同的二叉搜索树
题目链接 https://leetcode.com/problems/unique-binary-search-trees/description/ 题目描述 给定一个整数 n,求以 1 ... n ...
- [LeetCode]96. 不同的二叉搜索树(DP,卡特兰数)
题目 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ ...
- LeetCode 96. 不同的二叉搜索树(Unique Binary Search Trees )
题目描述 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 输出: 解释: 给定 n = , 一共有 种不同结构的二叉搜索树: \ / / / \ \ / / ...
- LeetCode 96 - 不同的二叉搜索树 - [DP]
假定 $f[n]$ 表示有 $n$ 个节点的二叉树,有多少种不同结构. 因此 $f[n] = \sum_{i=0}^{n-1} (f[i] \times f[n-1-i])$,选一个节点作为根节点,那 ...
- Leetcode:96. 不同的二叉搜索树
Leetcode:96. 不同的二叉搜索树 Leetcode:96. 不同的二叉搜索树 题目在链接中,点进去看看吧! 先介绍一个名词:卡特兰数 卡特兰数 卡特兰数Cn满足以下递推关系: \[ C_{n ...
- 【JavaScript】Leetcode每日一题-二叉搜索树的范围和
[JavaScript]Leetcode每日一题-二叉搜索树的范围和 [题目描述] 给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和. 示例1: 输入: ...
- 【python】Leetcode每日一题-二叉搜索树节点最小距离
[python]Leetcode每日一题-二叉搜索树节点最小距离 [题目描述] 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 . 示例1: 输入:root = [4 ...
- Leetcode题目96.不同的二叉搜索树(动态规划-中等)
题目描述: 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 ...
随机推荐
- HDU Ellipse(simpson积分)
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...
- thinkphp 利用GD库在图片上写文字
<?php /** * Created by PhpStorm. * User: Administrator */ namespace Home\Event; use \Think\Image; ...
- Java中枚举的相关应用
package example6; import org.junit.Test;/*1.什么是枚举? * 需要在颐堤港范围内取值,这个值只能是这个范围内的一个 * 使用枚举关键字enum * 枚举里也 ...
- canvas常用属性方法由浅下沉
首先引入<canvas></canvas>标签就不必说了. 其次就是得到canvas的2d环境了( var ctx = canvasDom.getContext('2d') ) ...
- rem和em的用法
1.rem转化为向素值的方法 rem单位转化为像素大小取决于根元素的字体大小,即HTML元素的字体大小,根元素字体大小乘以rem. 例:根元素的字体大小 16px,10rem 将等同于 160px,即 ...
- Robots协议(摘)
robots协议 Robots协议(也称为爬虫协议.机器人协议等)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓 ...
- C语言之一般树
1.一般树 将这种一般的树转化成我们熟悉的单链表形式,这有三层,每一层都可以看成单链表或者多个分散的单链表 数据节点如下: struct tree { int elem; ...
- python学习笔记:第11天 闭包及迭代器
目录 1. 函数名的使用 2. 闭包 3. 迭代器 1. 函数名的使用 其实函数名也是一个变量,但它是一个比较特殊的变量,与小括号配合可以执行函数的变量: 函数名其实和内存一样,也可以使用print查 ...
- 解决protobuf import路径的问题
网上关于protobuf import的文章不太详细,有些问题说的不全,比如import时的路径是在哪个目录中搜索的,比如: 我有一个这样的目录结构,我怎么在demo2/protoDemo2.prot ...
- vimrc 配置
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by" the call to : ...