不同的二叉搜索树II
思路
首先,先明确什么是二叉搜索树。
二叉搜索树:左子树上所有结点的值小于根结点值,右子树所有结点的值大于根结点值,并且左右子树均为二叉搜索树。又称为二叉排序树
在二叉搜索树I中,我们是这样做的:
假设 n 个结点存在二叉搜索树的个数是G(n),令f(i)为以 i 为根的二叉搜索树的个数,则
G(n) = f(1) + f(2) + ... + f(n)
当 i 为根结点时,其左子树结点个数为 i - 1个,右子树结点为n - i,则
f(i) = G(i - 1) * G(n - i)
综合两个公式可以得到卡特兰数公式
G(n) = G(0) * G(n - 1) + G(1) * G(n - 2) + ... + G(n - 1) * G(0)
但是,这道题不能只返回一个数字,还要将这些树构造出来,使用动态规划会非常麻烦。
我们知道,当 i 结点为根结点的时候,可以构成的二叉搜索树的个数是左子树集合的数量 * 右子树结合的数量,构造的过程无非是,取出左子树集合中的一个结点拼接在根结点,右结点同理。
所以,可以使用递归。
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<TreeNode> generateTrees(int n) {
if(0 == n){
return new LinkedList<TreeNode>();
}
return generateTrees(1, n);
}
public List<TreeNode> generateTrees(int start, int end){
List<TreeNode> res = new LinkedList<TreeNode>();
if(start > end){
res.add(null);
return res;
}
for(int i = start; i <= end; i++){
List<TreeNode> leftRes = generateTrees(start, i - 1);
List<TreeNode> rightRes = generateTrees(i + 1, end);
for(TreeNode left : leftRes){
for(TreeNode right : rightRes){
TreeNode node = new TreeNode(i);
node.left = left;
node.right = right;
res.add(node);
}
}
}
return res;
}
}