【发布时间】:2020-02-13 03:02:03
【问题描述】:
同构意味着一棵完全二叉树的任意子树交换自己可以与另一个相同。
答案肯定不是加泰罗尼亚数,因为加泰罗尼亚数的数量计算同构数。
【问题讨论】:
同构意味着一棵完全二叉树的任意子树交换自己可以与另一个相同。
答案肯定不是加泰罗尼亚数,因为加泰罗尼亚数的数量计算同构数。
【问题讨论】:
我假设n 节点是指n 内部节点。所以它将有2n+1 顶点和2n 边。
接下来,我们可以对二叉树进行排序,如下所示。具有更多节点的树更大。如果两棵树的节点数相同,则比较左侧,并通过比较右侧来打破平局。如果两棵树按此顺序相等,通过归纳法不难证明它们是同一棵树。
对于您的问题,我们可以假设对于每个同构类,我们只对该同构类中的 最大 树感兴趣。请注意,这意味着左子树和右子树在它们的同构类中也必须是最大的,并且左子树必须与右子树相同或大于右子树。
所以假设f(n) 是具有n 节点的非同构二叉树的数量。我们现在可以递归了。以下是我们的案例:
n=0 有一棵空树。n=1 有一个。一个有 2 片叶子的节点。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]
请注意,它开始时比加泰罗尼亚数字慢,但仍呈指数增长。
【讨论】:
//2 而不是/2,以避免浮点输出。另见oeis.org/A001190