【LeetCode】95. Unique Binary Search Trees II 解题报告(Python)

127 篇文章 2 订阅
102 篇文章 2 订阅

题目分析:

给定一个整数 n,生成所有由 1 … n 为节点所组成的二叉搜索树。
示例:
输入: 3
输出:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
解释:
以上的输出对应以下 5 种不同结构的二叉搜索树:
在这里插入图片描述

解题思路:

这一题可以用递归或递归+动态规划解,我们先说递归帮助理解,这一题的动态规划实际上时递归的一个优化。
这一题使用递归解涉及递归思想与二叉树搜索树,如果没有一定知识储备会很难想。这个题我看了好几个博客(其实都差不多),最后还是通过不断调试明白了原理。我们先通过递归的思想使用【LeetCode】96. Unique Binary Search Trees 的方法构造某个节点的所有左右子树,例如:

  1. 1进入程序作为第一个节点
  2. 它的左节点一定是None(没有比1小的)
  3. 开始添加1的右节点(可选2,3)
  4. 2进入程序
  5. 2的左节点为None(1用过了)
  6. 添加2的右节点(只有3可选)
  7. 3进入程序
  8. 3的左节点为None(1,2用过了)
  9. 3的右节点为None(没有比3大的)
  10. 构成了下图左侧的一棵搜索树
  11. 返回到第三步,这次选择3
  12. 3进入程序
  13. 3的左节点为2(1用过了)
  14. 2进入程序
  15. 2的左节点为None(1用过了)
  16. 添加2的右节点None(3用过了)
  17. 返回到第13步
  18. 3的右节点为None(没有比3大的)
  19. 构成了下图右侧的一棵搜索树(带左图的1,不再标写)
  20. 返回到第一步,以2作为程序第一个节点
  21. … …
    在这里插入图片描述

代码实现,递归的话我们要标记现在够成树的起点与终点(因为要知道哪些节点可选)def dfs(self, start, end):,从某一点i开始
能构成左子树的可选项时从start到i - 1(这个范围内的值小于i),同理能构成左子树的可选项时从i + 1到end,代码实现就是:

        for i in range(start, end + 1):
            Left_Tree = self.dfs(start, i - 1)
            Right_Tree = self.dfs(i + 1, end)

有了左右子树我们就可以开始以i为根节点构成一棵树,代码如下:

            for l_t in Left_Tree:
                for r_t in Right_Tree:
                    root = TreeNode(i)
                    root.left = l_t
                    root.right = r_t

这就是递归的基本思路了,动态规划就是建立一个字典存储每次start到end的子树形状,保存结果为后续相同的小子树直接返回结果,先把递归搞懂,递归+动态规划直接看代码即可。

提交代码1:(递归,Runtime: 64 ms, faster than 69.94% )

class Solution:
    def dfs(self, start, end):
        res = []
        if start > end: return [None]
        for i in range(start, end + 1):
            Left_Tree = self.dfs(start, i - 1)
            Right_Tree = self.dfs(i + 1, end)
            for l_t in Left_Tree:
                for r_t in Right_Tree:
                    root = TreeNode(i)
                    root.left = l_t
                    root.right = r_t
                    res.append(root)
        return res

    def generateTrees(self, n):
        if n == 0: return []
        return self.dfs(1, n)

提交代码2:(递归 + 动态规划,Runtime: 56 ms, faster than 96.26% )

class Solution:
    def generateTrees(self, n: 'int') -> 'List[TreeNode]':
        if not n: return []
        if n == 1: return [TreeNode(1)]
        return self.dfs(1, n, {})

    def dfs(self, start, end, cache):
        if start > end: return [None]
        if start == end: return [TreeNode(start)]
        if (start, end) in cache: return cache[(start, end)]
        trees = []
        for i in range(start, end + 1):
            for l_t in self.dfs(start, i - 1, cache):
                for r_t in self.dfs(i + 1, end, cache):
                    root = TreeNode(i)
                    root.left = l_t
                    root.right = r_t
                    trees.append(root)
        cache[(start, end)] = trees
        return trees

参考博客1参考博客2,以及LeetCode 95. Unique Binary Search Trees II提交代码中的第一个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值