打卡每日一题!!!
今天为大家分享的还是一道动态规划类型的题目,可能猛地看起来有点像考察二叉树的知识,回归其本质还是动态规划的内容。
题目描述:
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
题目示例:
这道题首先你要有一定的知识储备:
- 1.什么叫二叉搜索树
- 2.动态规划的思路
1.什么叫二叉搜索树?
左子树一定小于其父节点,右子树一定大于其父节点
2.何为动态规划?
动态规划的本质就是找状态转移方程,然后从起始点条件一点点的递推出结果。
我们先假设n个结点对应的二叉搜索树的个数为:G(n);
记f(i):表示为以 i 为根的二叉搜索树的个数。
则有G(n)=f(1)+f(2)+f(3)+…+f(n)
以i为根节点,则其左子树结点个数为:i-1,右子树结点个数为:n-i
比如我们的n=7,i=3,则对应的结点序列为:[1,2,3,4,5,6,7]
则左子树的结点有:[1,2]
右子树的结点有:[4,5,6,7]
则f(i)=G(i-1)*G(n-i)
于是G(n)=G(0)*G(n-1)+G(1)*G(n-2)+G(2)*G(n-3)+…+G(n-1)*G(0)
初始条件:
- n=0时,就只有一种可能,所以:G(0)=1
- n=1时,也只有一种可能,所以:G(1)=1
G(2)=G(0)*G(2-1)+G(1)*G(2-2)
G(3)=G(0)*G(3-1)+G(1)*G(3-2)+G(2)*G(3-3)
以此例推
代码如下:(PS:Java版)
public int numTrees(int n) {
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++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
上面的dp就是我们的G(n)