【问题标题】:How many non-isomorphic full binary trees can n nodes generate?n 个节点可以生成多少个非同构完整二叉树?
【发布时间】:2020-02-13 03:02:03
【问题描述】:

同构意味着一棵完全二叉树的任意子树交换自己可以与另一个相同。

答案肯定不是加泰罗尼亚数,因为加泰罗尼亚数的数量计算同构数。

【问题讨论】:

    标签: algorithm math tree


    【解决方案1】:

    我假设n 节点是指n 内部节点。所以它将有2n+1 顶点和2n 边。

    接下来,我们可以对二叉树进行排序,如下所示。具有更多节点的树更大。如果两棵树的节点数相同,则比较左侧,并通过比较右侧来打破平局。如果两棵树按此顺序相等,通过归纳法不难证明它们是同一棵树。

    对于您的问题,我们可以假设对于每个同构类,我们只对该同构类中的 最大 树感兴趣。请注意,这意味着左子树和右子树在它们的同构类中也必须是最大的,并且左子树必须与右子树相同或大于右子树。

    所以假设f(n) 是具有n 节点的非同构二叉树的数量。我们现在可以递归了。以下是我们的案例:

    1. n=0 有一棵空树。
    2. n=1 有一个。一个有 2 片叶子的节点。
    3. n > 1。让我们遍历右边的数字m。如果2m+1 < n 则右侧有f(m) 最大树,左侧有f(n-m-1),所有这些对于f(m) * f(n-m-1) 都是最大的。如果2m+1 = n,那么我们想要在右边有一个最大的树,有m 节点,左边有一个最大的树,有m 节点,右边的树必须小于或等于左边。但是有一个众所周知的公式可以说明有多少种方法可以做到这一点,那就是f(m) * (f(m) + 1) / 2。最后我们不能有n < 2m+1,因为在这种情况下我们没有最大树。

    使用它,您应该能够编写一个递归函数来计算答案。

    UPDATE下面是这样一个函数:

    cache = {0: 1, 1:1}
    def count_nonisomorphic_full_trees (n):
        if n not in cache:
            answer = 0
            for m in range(n):
                c = count_nonisomorphic_full_trees(m)
                if n < m+m+1:
                    break
                elif n == m+m+1:
                    answer = answer + c*(c+1)//2
                else:
                    d = count_nonisomorphic_full_trees(n-m-1)
                    answer = answer + c*d
            cache[n] = answer
        return cache[n]
    

    请注意,它开始时比加泰罗尼亚数字慢,但仍呈指数增长。

    【讨论】:

    • 感谢您分享您的解决方案,这真的很有帮助。我在阅读Leetcode 849 时遇到了这个问题。我也很好奇如何输出树列表并在我们的非同构案例中将它们可视化,例如 Leetcode 上的示例。期待您的回答!
    • P.S.如果你能提供一些关于你上面提到的“众所周知的公式”的资料,我将不胜感激。
    • @wilton_hwang 有关公式,请参见 byjus.com/maths/triangular-numbers。实际上生成树木听起来像是一个有趣的挑战。我得考虑一下。
    • 建议使用//2 而不是/2,以避免浮点输出。另见oeis.org/A001190
    • @MarkDickinson 谢谢,已修复。我还研究了生成特定的树,遗憾的是,有一个复杂的二分搜索比我的好奇心所证明的要多。
    猜你喜欢
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2011-06-09
    • 1970-01-01
    • 2012-08-30
    • 2013-07-28
    • 2021-10-15
    相关资源
    最近更新 更多