C# leetcode 之 096 不同的二叉搜索树
题目描述
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
二叉搜索树定义
左子树上所有节点的值小于根节点, 右子树上左右节点的值大于根节点, 并且左右子树也为二叉搜索树
解题思路
根据二叉搜索树定义可知, 针对 1 .. n 的排序序列, 选取其中任意一个元素i则1到i-1的元素为左子树节点, i+1到n为右子树的节点. 题目中问的是一共有多少种二叉树, 所以其实不用关心二叉树中节点的值. 由此可知一个树只要节点数相同则生成的二叉搜索树的数量相同. 我们在求解的过程中可以将不同的节点数对应的二叉搜索树的数量存到一个字典中. 又因为前面提到的选取i后可以将问题划分为更小的问题. 所以符合动态规划的特性. 下面尝试使用动态规划进行分析.
我们假设 1 .. n 中包含的二叉树个数为 G(n) 则可得出公式
\[G(n) = \sum_{i=1}^{n} G(i - 1) * G(n - i)
\]
\]
其中 i - 1
为左子树的元素个数, n - i
为右子树的元素个数, 并且G(0)为0
代码实现
实现方式1: 迭代实现
public int NumTrees(int n)
{
var ar = new int[n + 1];
ar[0] = 1;
for (var i = 1; i <= n; i++)
{
var count = 0;
for (var j = 1; j <= i; j++)
{
count += dic[j - 1] * dic[i - j];
}
dic[i] = count;
}
return dic[n];
}
实现方式2: 递归实现
private readonly IDictionary<int, int> _dic = new Dictionary<int, int>
{
[0] = 1
};
public int NumTrees(int n)
{
if (_dic.TryGetValue(n, out var val))
{
return val;
}
var count = 0;
for (var i = 1; i <= n; i++)
{
count += NumTrees(i - 1) * NumTrees(n - i);
}
_dic[n] = count;
return count;
}