96.不同的二叉搜索树
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
示例:
思路
第一反应,只记得二叉搜索树的性质(中序遍历可以将其变为一个单调递增的序列)
找不到规律,先举例分析。把只有一个节点,只有两个节点的情况给画出来:
n = 1、2时情况如下:
观察n = 3 的情况
当1为头节点时,其右子树有两个节点,其右子树节点的布局与n = 2 时的布局一样;
当2为头节点时,其左右子树各有一个节点,与n = 1时的布局一样;
当3为头节点时,其左子树有两个节点,其左子树节点的布局与n = 2 时的布局一样。
看到此处,我们就找到了重叠的子问题,其实离归纳出递推公式只剩一步之遥
然后去考察dp[3],其实就是以1为头节点的BST的数量 + 以2为头节点的BST的数量 + 以3为头节点的BST的数量。
-
以1为头节点的BST数量:左子树节点为0的数量 * 右子树为 2的数量
-
以2为头节点的BST数量:左子树节点为1的数量 * 右子树为1的数量
-
以3为头节点的BST数量:同情况1
1.dp数组及其下标含义
dp[i]: 表示1 ~ i个节点组成的BST的数量
2.确定递推公式
在上面分析中,其实可以得出关系,dp[i] += dp[以j为头节点的左子树节点个数] * dp[以j为头节点的右子树节点个数]
j是头节点元素,作用是从i遍历到最后一个
所以可以得出递推公式:dp[i] += dp[j - 1] * dp[i - j];
3.dp数组初始化
dp[0] : 没有节点的BST的数量,因为空节点也是一棵空的二叉搜索树,所以dp[0] = 1
4.确定遍历顺序
根据递推公式可知:dp[i] += dp[j - 1] * dp[i - j];
int dp[20] = {0}; dp[0] = 1; // 空节点相当于也是一棵二叉搜索树 // dp[1] = 1; 一个节点时只有一种 // dp[2] = 2; 两个节点是有两种 for (int i = 1; i <= n; i ++) { for (int j = 1; j <= i; j ++) { 左子树节点数 * 右子树节点数 dp[i] += dp[j - 1] * dp[i - j]; } } return dp[n];