不同的二叉搜索树II

image-20200721202629318

思路

首先,先明确什么是二叉搜索树。

二叉搜索树:左子树上所有结点的值小于根结点值,右子树所有结点的值大于根结点值,并且左右子树均为二叉搜索树。又称为二叉排序树

二叉搜索树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;
    }
}
posted @ 2020-07-21 21:07  zjy4fun  阅读(211)  评论(0编辑  收藏  举报