卡特蘭數(Catalan Number)及其應用

定義

卡特蘭數是一個常出如今各類計數問題中的數列, 其知足的遞推方程以下:
$$C(n) = \sum_{k=0}^{n-1} C(k) \times C(n-1-k), n \gt 0$$
令初始值$C(0) = 1$,其前幾項爲:1, 1, 2, 5, 14, 42...
其通項公式有多種寫法,如用生成函數法能夠直接由以上遞推方程求出,這裏暫且不表,僅取一種簡潔且易於計算的形式:
$$C(n) = \frac{1}{n+1}\binom{2n}{n}$$面試

應用

卡特蘭數能夠應用於許多有趣的組合數學問題及CS中的計數問題,列舉其中部分:segmentfault

  1. n個數共有多少種不一樣的出棧序列? -- C(n).
  2. n對括號共有多少種合法配對形式?e.g., n = 2,()(), (()) -- C(n).
  3. 給n+1個相乘的數加括號,e.g., n=2, ((ab)c), (a(bc)). 共有多少種方法? --- C(n).
  4. 有n個節點的二叉樹(問二叉搜索樹(BST)也同樣), 有多少種不一樣構成形式?-- C(n).
  5. 有n+1個葉子結點的滿二叉樹,共有多少種? -- C(n).
  6. 將凸n+2邊形以不相交的對角線分割爲n個三角形,共有多少種方法? -- C(n).
  7. n個-1和n個1構成的序列中,知足任意前綴和都大於0的有多少種? -- C(n). 這個問題能夠將-1當作入棧,1當作出棧,前綴和大於0的序列等價於出棧序列。

由此衍生出許多問題,一般均可以寫出定義中的遞推方程。如一道筆試題:
在圖書館一共6我的在排隊,3個還《面試寶典》一書,3個在借《面試寶典》一書,圖書館此時沒有了面試寶典了,求他們排隊的總數?
-- 相似例題7,由C(3)=5,但注意組合的問題都認爲物品是相同的,這裏還要考慮3個不一樣的人的排列,所以總數: 5 * 3!* 3! = 180.函數

計算

如今上code來計算第n個組合數$C(n)$. 分別從遞推公式和通項公式出發有兩種方法:code

動態規劃

根據遞推公式很容易寫出動規, 在忘記通項公式的時候能夠使用, 大多數狀況不會超時。get

int catalan(int n) {
    vector<int> dp(n+1, 0);
    for (int i = 1; i <= n; ++i)
        for (int j = 0; j <= i - 1; ++j)
            dp[i] += dp[j] * dp[i-1-j];
    return dp[n];
}
  • 時間複雜度:$O(n^2)$
  • 空間複雜度:$O(n)$

計算組合數

若是記得通項公式,那麼直接計算組合數更快,利用我在另外一篇文章的提到的方法compute_binomial 能夠在O(n)時間完成.數學

int catalan(int n) {
    return compute_binomial(2*n, n) / (n+1);
}
  • 時間複雜度:$O(n)$
  • 空間複雜度:$O(1)$
相關文章
相關標籤/搜索