卡塔蘭數
卡塔蘭數的一般項公式為
前幾項為 (OEIS中的數列A000108):
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, 18367353072152, 69533550916004, 263747951750360,
1002242216651368, 3814986502092304, 14544636039226909, 55534064877048198, 212336130412243110, 812944042149730764, 3116285494907301262, 11959798385860453492, 45950804324621742364, ...
性質
Cn的另一個表達形式為 所以,Cn是一個自然數;這一點在先前的通項公式中並不顯而易見。這個表達形式也是André對前一公式證明的基礎。
遞推關係
它也滿足
這提供了一個更快速的方法來計算卡塔蘭數。
卡塔蘭數的漸近增長為
它的含義是左式除以右式的商趨向於1當n → ∞。(這可以用n!的斯特靈公式來證明。)
所有的奇卡塔蘭數Cn都滿足。所有其他的卡塔蘭數都是偶數。
應用
- Cn表示長度2n的dyck word的個數。Dyck word是一個有n個X和n個Y組成的字串,且所有的首碼字串皆滿足X的個數大於等於Y的個數。以下為長度為6的dyck words:
XXXYYY XYXXYY XYXYXY XXYYXY XXYXYY
- 將上例的X換成左括弧,Y換成右括弧,Cn表示所有包含n組括弧的合法運算式的個數:
((())) ()(()) ()()() (())() (()())
- Cn表示有n個節點群組成不同構二叉樹的方案數。中,n等於3,圓形表示節點,月牙形表示什麼都沒有。
- Cn表示有2n+1個節點群組成不同構滿二叉樹(full binary tree)的方案數。中,n等於3,圓形表示內部節點,月牙形表示外部節點。本質同上。
證明:
令1表示進棧,0表示出棧,則可轉化為求一個2n位、含n個1、n個0的位元,滿足從左往右掃描到任意一位時,經過的0數不多於1數。顯然含n個1、n個0的2n位位元共有個,下面考慮不滿足要求的數目。
考慮一個含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的位元。反之亦然(相似的思路證明兩者一一對應)。
從而。證畢。
應用2的C++代碼實現如下
#include <iostream>#include <vector>using namespace std;/*count[0]存著左括弧數目,count[1]存著右括弧數目。一開始kind中壓入左括弧,因為第一個肯定是左括弧。然後count數組初始化為n-1個左括弧,n個右括弧。然後我們遞迴的處理。如果剩餘左括弧數count[0]大於0,就可以把左括弧壓棧。而對於右括弧,棧中左括弧個數必須多於右括弧個數,也就是剩餘右括弧個數大於左括弧個數,即count[1]>count[0]時,才能將右括弧壓棧。如果棧中元素個數達到2n時,就把棧中元素輸出。*/void func(vector<char>kind,int count[],int n){ static int cnt = 0; if(count[0]>=1) { kind.push_back('('); count[0]--; func(kind,count,n); count[0]++; kind.pop_back(); } if((count[1]>=1) && (count[1]>count[0])) { kind.push_back(')'); count[1]--; func(kind,count,n); count[1]++; kind.pop_back(); } if(kind.size()==2*n) {cnt++; vector<char>::iterator iter; for(iter=kind.begin();iter!=kind.end();iter++) { cout<<(*iter)<<" "; }cout << "cnt = " << cnt << endl; cout<<endl; }}int main(){ int n; cout << "please input the number of ():" << endl; cin>>n; int count[2]={n-1,n}; vector<char>kind; kind.push_back('('); func(kind,count,n); return 0;}
註:上述部分內容摘抄與維基百科