美文网首页
Golang 实现卡特兰数

Golang 实现卡特兰数

作者: Hawken | 来源:发表于2018-03-15 10:51 被阅读54次

Golang 实现卡特兰数

卡特兰数又称卡塔兰数,卡特兰数是组合数学中一个常出现在各种计数问题中的数列。前20项为:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190。

原理

  1. 令h(0)=1,h(1)=1,catalan数满足递推式:

    h(n)= h(0)h(n-1)+h(1)h(n-2) + ... + h(n-1)*h(0) (n>=2)

    例如:

    h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2

    h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5

  2. 另类递推式:

    h(n)=h(n-1)*(4*n-2)/(n+1)

  3. 递推关系的解为:

    h(n)=C(2n,n)/(n+1) (n=0,1,2,…)

  4. 递推关系的另类解为:

    h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,…)

性质

卡塔兰数的一般项公式为:

一般项公式.png ​
Cn的另一个表达形式为:
另一个表达式.png
递推关系: 递推关系.png

它也满足


这提供了一个更快速的方法来计算卡塔兰数。

应用

实质上都是递推等式的应用

其实我们只需要记住它的一般项公式就好了,平时用到一般只需要用到它。

  • 括号化

    矩阵连乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n)种)

  • 出栈次序

    一个栈无穷大的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?(h(n)个)

    证明:

    令1表示进栈,0表示出栈,则可转化为求一个2n位、含n个1、n个0的二进制数,满足从左往右扫描到任意一位时,经过的0数不多于1数。显然含n个1、n个0的2n位二进制数共有

    二进制数.png

个,下面考虑不满足要求的数目。

考虑一个含n个1、n个0的2n位二进制数,扫描到第2m+1位上时有m+1个0和m个1(容易证明一定存在这样的情况),则后面的0-1排列中必有n-m个1和n-m-1个0。将2m+2及其以后的部分0变成1、1变成0,则对应一个n+1个0和n-1个1的二进制数。反之亦然(相似的思路证明两者一一对应)。

从而 进栈.png

证毕。

  • Cn表示有n个节点组成不同构二叉树的方案数。**

  • Cn表示有2n+1个节点组成不同满二叉树(full binary tree)的方案数。**

  • dyck word

    Cn表示长度2n的dyck word的个数。Dyck word是一个有n个X和n个Y组成的字串,且所有的前缀字串皆满足X的个数大于等于Y的个数。以下为长度为6的dyck words:

    XXXYYY XYXXYY XYXYXY XXYYXY XXYXYY

  • n对括号正确匹配数目

    将上例的X换成左括号,Y换成右括号,Cn表示所有包含n组括号的合法运算式的个数:

    ((())) ()(()) ()()() (())() (()())

  • 其他应用还用很多,可以去百度百科和维基百科上看,这里就不赘述了。

用 Golang 实现

import (
    "fmt"
    "math/big"
)
// 由于阶乘结果的数超出 int64 的范围,所以用到了 math/big 包来实现大数。


// 输出前20个卡特兰数
func main() {
    for i := int64(0); i < 20; i++ {
        fmt.Println(catalan(i))
    }
}
// 求卡特兰数
func catalan(n int64) *big.Int {
    one := big.NewInt(1) // 过渡值

    denominator := factorial(2 * n)
    divisor := one.Mul(factorial(n+1), factorial(n))
    return one.Div(denominator, divisor)
}
// 阶乘
func factorial(n int64) *big.Int {
    sum := big.NewInt(1)
    for i := int64(1); i <= n; i++ {
        sum.Mul(sum, big.NewInt(i))
    }
    return sum
}

参考

相关文章

  • Golang 实现卡特兰数

    Golang 实现卡特兰数 卡特兰数又称卡塔兰数,卡特兰数是组合数学中一个常出现在各种计数问题中的数列。前20项为...

  • 卡特兰数:hdu-2067 小兔的棋盘&&火车出栈问题

    卡特兰数,一串神奇的数字,1,2,5,14...... 首先了解一下卡特兰数. 卡特兰数(好像很有用的说) - C...

  • AVL

    LOG(n) 卡特兰数 叉姐

  • 数学 | 卡特兰数

    卡特兰数 定义 卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出...

  • 卡特兰数

  • 卡特兰数

    之前看算法导论时,讲了给定几个数字,能构造出几种二叉树,当时只想到排列组合的解决方法,极其复杂又不好记,过段时间还...

  • 卡特兰数

    https://zhuanlan.zhihu.com/p/31317307 火车进出栈问题和腾讯那道猜拳游戏是一样...

  • 卡特兰数

    卡特兰数是一种经典的组合数,经常出现在各种计算中,其前几项为 :1, 2, 5, 14, 42,132, 429,...

  • 卡特兰数

    名字来源比利时数学家卡塔兰。卡塔兰:Catalan 数列满足 通项: 给定n个节点,能构成的二叉搜索树个数为Cn。...

  • 卡特兰数

    题:12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?解:...

网友评论

      本文标题:Golang 实现卡特兰数

      本文链接:https://www.haomeiwen.com/subject/batuuxtx.html