95. 不同的二叉搜索树 II

这里写图片描述
参考链接:https://blog.csdn.net/happyaaaaaaaaaaa/article/details/51635367


在参考原本的基础上,使用一个辅助数组,保存递归中的值,避免重复计算。

//递归实现
public List<TreeNode> generateTrees(int n) {
    if (n < 1) return new ArrayList<>();
    //利用一个辅助数组保存中间的值,避免重复求取,但是也会导致有些子树的结点是公共的
    List[][] dp = new List[n + 2][n + 2];
    return generateTrees(1, n,dp);
}

private List<TreeNode> generateTrees(int start, int end, List[][] dp) {
    List<TreeNode> res = new ArrayList<>();
    if (end < start) {
        res.add(null);
        return res;
    }
    for (int i = start; i <= end; i++) {
        List<TreeNode> list1 = dp[start][i - 1];
        if (list1 == null) {
            //递归,并将结果保存下来
            list1 = generateTrees(start, i - 1, dp);
            dp[start][i - 1] = list1;
        }
        //(start,i-1)为左子树,遍历不同的左子树组合
        for (TreeNode left : list1) {
            List<TreeNode> list2 = dp[i + 1][end];//当 i = n 时,就需要求 dp[n+1][end] 的值
            if (list2 == null) {
                //递归,并将结果保存下来
                list2 = generateTrees(i + 1, end, dp);
                dp[i + 1][end] = list2;
            }
            //(i+1,end)为右子树,遍历不同的右子树组合
            for (TreeNode right : list2) {
                TreeNode root = new TreeNode(i);
                root.left = left;
                root.right = right;
                res.add(root);
            }
        }
    }
    return res;
}

主要就是利用分治的思想(可以参考 【96. 不同的二叉搜索树】),以 [start,end] 中的某一个为根结点 i,然后划分左右子树 [start,i-1](左子树) 和 [i+1,end](右子树),分别遍历两边子树的不同组合结果,并进行拼合。

因为用到了一个辅助的 List<TreeNode> 数组保存递归的值,所以可以避免一些重复的递归,但是也会因重复利用保存的值,导致一些子树的结点是公共的。如下:

(打印 n = 3 时的结果,前面的数字为 TreeNode 的哈希值,括号里的数组为 TreeNode 的 val 值)

这里写图片描述
如上红线划记的两部分,红线上的表示包括的,红线下的表示排除的元素(因为是按树的层次遍历打印的),这两部分就是重复的。

如果不用辅助数组保存,则每次递归都是生成新的 List<TreeNode>,此时就不会出现子树的结点是公共的情况。如下:
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值