# will build list such that numTrees[n] is the number of distinct trees with n leaves numTrees = [1,1,1] # seed results with 1 way to trivially have a tree with 2 or less leaves # How many ways can n things be distinctly divided into groups of size a and b (for n=a+b) def distinctGroups(n,a,b): ans = 1 for k in range(b+1,n+1): # first compute factorial(n)/factorial(b) ans = ans*k for k in range(1,1+a): # now divide out factorial(a) ans = ans // k if a == b: # SPECIAL CASE: for equal groups divide out symmetry ans = ans // 2 # (i.e. doesn't matter which group is "a" and which group is "b") return ans # compute for n=3 and onward... for n in range(3,31): count = 0 for a in range(1,1+n//2): # a is size of the smaller group (unless a,b equal) b = n-a # determine number of ways do uniquely divide group of n into # two groups of a and b respectively. grouping = distinctGroups(n,a,b) # for each such grouping there are numTrees[a] ways to design # the subtree of size a, and numTrees[b] ways to design the # subtree of size b count += grouping * numTrees[a] * numTrees[b] numTrees.append(count) print(n, count)