Re:从零开始的算法学习

213 阅读1分钟

个人学习之用,如果有看客觉得哪里不清楚或者有错误,欢迎指出,会尽量及时更新。

算法

卡特兰数 Catalan Number

卡特兰数可用下式算出(法1)

f(n)=\frac{C_{2n}^{n}}{n+1}

卡特兰数递推式(法2) 卡特兰数是符合以下公式的数列

f(n) = \sum_{k=0}^{n-1}f(k)f(n-1-k)

上式推导方法参见96. 不同的二叉搜索树,首先可以注意到本题相当于满足编号中序遍历为1-n的二叉树的个数,又相当于n个相同点组成二叉树的个数。

做法是DP,集合为n个点时不同的二叉搜索树,属性为数量,sum 左右子树的可能种数之积。

卡特兰数适用的问题

  • 相同 n 个点组成的不同二叉树的个数
  • 中序遍历为 1-n 的二叉树的个数
  • 节点值为 1-n 的二叉搜索树的个数
  • n对( )的合法组合(栈)
  • n个0,n个1,条件:任何前缀中0的个数不少于1的个数
  • 1, 2, ···, n 合法的进栈出栈序列的个数
  • 不同的操作序列 -> 不同的排列

所以卡特兰数可以转化为求组合数的问题

补充:杨辉三角C_{n}^{m}=C_{n-1}^{m}+C_{n-1}^{m-1}

// n 比较小的时候,杨辉三角,递推 O(n^2)

// n 在10e5 质数 乘法逆元 O(nlogn)

// n 在10e18 lucas 定理

// 高精度 阶乘分解

最简单的方法,用Python和java写,方便解决大数。

n = int(input())
# catalan number: C_2n^n/(n+1) 所以要2*n
C = [[0]*(2*n+1) for _ in range(2*n+1)]

for i in range(0, 2*n+1):
   for j in range(0, i+1):
       if not j:
           C[i][j] = 1
       else:
           C[i][j] = C[i-1][j] + C[i-1][j-1]
   
print(C[2*n][n]//(n+1))