具有相等值的二叉树的数量

时间:2013-11-24 10:40:48

标签: binary-tree

有一系列值:

1 - n_1次

2 - n_2次

...

k - n_k次

这个节点有多少棵树?

我创造了简单的algorythm:

int get_count(const vector<int> n_i) {
  if (n_i.size() <= 1) {
    return 1;
  } else {
    int total_count = 0;
    for (int i = 0; i < n_i.size(); ++i) {
      vector<int> first;
      vector<int> second;
      for (int j = 0; j < i; ++j) {
        first.push_back(n_i[j]);
      }
      if (n_i[i] != 1) {
        second.push_back(n_i[i] - 1);
      }
      for (int j = i + 1; j < n_i.size(); ++j) {
        second.push_back(n_i[j]);
      }
      total_count += (get_count(first) * get_count(second));
    }
    return total_count;
  }
}

因为

#(n_1,n_2,... n_k)=#(n_1 - 1,n_2,...,n_k)+#(n_1)#(n_2 - 1,... n_k)+ ... + #(n_1,...,n_k - 1)

#(0,n_i,n_j,...)=#(n_i,n_j,...)

但我的代码太慢了。

例如,根据Cathalan的数字是否有最终公式?

1 个答案:

答案 0 :(得分:1)

我猜这个问题可以分解为计算排列数和计算给定大小的二叉树数量。我将我的初始递归Java代码(放弃n1 = 10,n2 = 10,n3 = 10)转换为这个迭代的代码:

static int LIMIT = 1000;

static BigInteger[] numberOfBinaryTreesOfSize = numberOfBinaryTreesBelow(LIMIT);
static BigInteger[] numberOfBinaryTreesBelow(int m) {
    BigInteger[] arr = new BigInteger[m];
    arr[0] = BigInteger.ZERO;
    arr[1] = arr[2] = BigInteger.ONE;
    for (int n = 3; n < m; n++) {
        BigInteger s = BigInteger.ZERO;
        for (int i = 1; i < n; i++)
            s = s.add(arr[i].multiply(arr[n - i]));
        arr[n] = s;
    }
    return arr;
}

static BigInteger[] fac = facBelow(LIMIT);
static BigInteger[] facBelow(int m) {
    BigInteger[] arr = new BigInteger[m];
    arr[0] = arr[1] = BigInteger.ONE;
    for (int i = 2; i < m; i++)
        arr[i] = arr[i - 1].multiply(BigInteger.valueOf(i));
    return arr;
}

static BigInteger getCountFast(int[] arr) {
    // s: sum of n_i
    int s = 0; for (int i = 0; i < arr.length; i++) { s += arr[i]; }
    // p: number of permutations
    BigInteger p = fac[s]; for (int i = 0; i < arr.length; i++) { p = p.divide(fac[arr[i]]); }
    BigInteger count = p.multiply(numberOfBinaryTreesOfSize[s]);
    return count;
}

public static void main(String[] args) {
    System.out.println(getCountFast(new int[]{ 150, 150, 150, 150, 150 }));
}

LIMIT限制了n_i的总和。上面的例子在我的机器上大约需要两秒钟。也许它可以帮助您使用C ++解决方案。