1. 程式人生 > >棧 | 卡特蘭數(Catalan number)

棧 | 卡特蘭數(Catalan number)

文章目錄

1.棧與卡特蘭數的關係

棧是計算機中經典的資料結構,我們也會遇到一個常見的問題:一共有多少種合法的出棧順序?

先說一下什麼是合法的出棧序列, 凡是合法序列都遵循以下規律:即對於出棧序列中的每一個數字,在它後面的、比它小的所有數字,一定是按遞減順序排列的。
例如:有數字1 2 3 4 依次入棧,那麼他們的出棧順序中:

  • 4321合法:4後面比它小的數是321,並且321遞減;3後面比它小的是21,並且21遞減。
  • 3421合法:3後面比它小的是21,並且21遞減;4後面比它小的是21,並且21遞減。
  • 1423不合法:4後面比它小的是23,23不是遞減。

所以到底有多少種合法序列呢?
答案就是:合法出棧數目==卡特蘭數


2.卡特蘭數

卡特蘭數又稱卡塔蘭數,卡特蘭數是組合數學中一個常出現在各種計數問題中的數列。以比利時的數學家歐仁·查理·卡塔蘭 (1814–1894)的名字來命名。(卡特蘭數百度百科
公式①:
f 0

= 1 f 1 = 1 f(0)= 1,f(1)= 1

f n = C n 2 n n + 1 = c n 2 n c n 1 2 n   n = 0 1 2 f(n)= \frac{C^{2n}_{n}}{n+1}= c^{2n}_n-c^{2n}_{n-1} (n=0,1,2,……)
公式②:
h 0 = 1 h 1 = 1 h(0)= 1,h(1)= 1
h ( n ) = h ( 0 ) h ( n 1 ) + h ( 1 ) h ( n 2 ) + . . . + h ( n 1 ) h ( 0 )   ( n > = 2 ) h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0)  (n>=2)

注意!!!
程式運算時使用第二種方法(第一種在n>15時就溢位了)

//方法一,m>15就溢位了
#include<iostream>
using namespace std;
int main()
{
	int m;
	cin>>m;
	long long int result=1;
	for(int i=m+1;i<=m*2;i++)
	{
		result*=i;
	}
	for(int i=2;i<=m;i++)
	{
		result/=i;
	}
	cout<<result/(m+1)<<endl;
	return 0;
}
//方法二
#include <iostream>
using namespace std;
int main()
{
    int n,f[20]={0};
    cin>>n;
    f[0]=1;f[1]=1;
    for(int i=2;i<=n;i++)
       for(int j=0;j<i;j++)
          f[i]+=f[j]*f[i-j-1];
          cout<<f[n];
    return 0;
}


3.擴充套件

知道數量也要知道數量是怎麼出來的——動態規劃


4.相關題目

題目描述:
棧是計算機中經典的資料結構,簡單的說,棧就是限制在一端進行插入刪除操作的線性表。棧有兩種最重要的操作,即pop(從棧頂彈出一個元素)和push(將一個元素進棧)。
在這裡插入圖片描述
棧的重要性不言自明,任何一門資料結構的課程都會介紹棧。寧寧同學在複習棧的基本概念時,想到了一個書上沒有講過的問題,而他自己無法給出答案,所以需要你的幫忙。
寧寧考慮的是這樣一個問題:一個運算元序列,從1,2,一直到n(圖示為1到3的情況),棧A的深度大於n。
現在可以進行兩種操作,

  1. 將一個數,從運算元序列的頭端移到棧的頭端(對應資料結構棧的push操作)
  2. 將一個數,從棧的頭端移到輸出序列的尾端(對應資料結構棧的pop操作)
    使用這兩種操作,由一個運算元序列就可以得到一系列的輸出序列,下圖所示為由1 2 3生成序列2 3 1的過程。(原始狀態如上圖所示)

在這裡插入圖片描述

你的程式將對給定的n,計算並輸出由運算元序列1,2,…,n經過操作可能得到的輸出序列的總數。

輸入: 輸入檔案只含一個整數n(1≤n≤18)
輸出: 輸出檔案只有一行,即可能輸出序列的總數目
樣例輸入:

3

樣例輸出:

5

答案: