持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。通俗来讲,就是返回n个节点的二叉树有几种形状。
解析
当n = 1时,我们可以很明显的知道,二叉树的形状只有一种。
当n = 2时,我们依然可以明显的知道,二叉树的形状只有两种。
当n = 3时,情况就稍微复杂点,但是通过我聪明的小脑依然可以把每种情况都画出来。
聪明的小伙伴可能发现了,n=3时,它的根节点的左子树和右子树不就是由n={0,1,2}的二叉树拼凑起来的嘛? 按照图片顺序可知每个n=3二叉树的拼凑方式:
- left:
n=0right:n=2 - left:
n=0right:n=2 - left:
n=1right:n=1 - ....
不难发现,就是将每种比n小的二叉树当作左右子树(左右子树节点数的和等于n-1,减1是因为不计算根节点),并将左右子树的笛卡尔积相加就能得到最终结果。发现规律后,我们可以用动态规划来解决这道题。
设计数组record[]来记录n个节点的二叉树有多少种形状。通过动态规划的原理从n=1开始不断向后求出结果,直到n=n,最后返回结果即可。
这题限制了n的范围(1~19),我们先计算出来每个结果,通过打表也是可行的,但最后发现因为计算简单,且n的范围较小,两者的效率和速度相差不大。
代码
class Solution {
public int numTrees(int n) {
int[] record = new int[n + 1];
//初始化
record[0] = 1;
for(int i = 1; i <= n;i++){
for(int j = 0; j < i; j++){
record[i] += record[j] * record[i-j-1];
}
}
return record[n];
}
}
打表的代码
class Solution {
int[] record = new int[]{1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,2674440,9694845,35357670,129644790,477638700,1767263190};
public int numTrees(int n) {
return record[n];
}
}