1. 程式人生 > >資料結構_任意N個元素有多少種出棧順序(卡特蘭數證明)

資料結構_任意N個元素有多少種出棧順序(卡特蘭數證明)

1.飯後,姐姐洗碗,妹妹把姐姐洗過的碗一個一個地放進碗櫥摞成一摞。一共有n個不同的碗,洗前也是摞成一摞的,也許因為小妹貪玩而使碗拿進碗櫥不及時,姐姐則把洗過的碗摞在旁邊,問:小妹摞起的碗有多少種可能的方式?

2.給定n個數,有多少種出棧序列?

3.一個有n個1和n個-1組成的字串,且前k個數的和均不小於0,那這種字串的總數為多少?

這三個問題具有相同的結構,三個問題是可以互相轉化。將姐姐放碗看做入棧操作,將妹妹放碗看做出棧操作。則問題一變為問題二。將入棧操作記為1,出棧記為-1,問題2變為問題3。

問題的答案是一個著名的數列,卡特蘭數。該問題的代數解法比較抽象,而運用到幾何上,用圖片來描述,卻有讓人恍然大悟的感覺。

    事實上,可以認為問題是,任意兩種操作,要求每種操作的總次數一樣,且進行第k次操作2前必須先進行至少k次操作1。我們假設一個人在原點,操作1是此人沿右上角45°走一個單位(一個單位設為根號2,這樣他第一次進行操作1就剛好走到(1,1)點),操作2是此人沿右下角45°走一個單位。第k次操作2前必須先進行至少k次操作1,就是說明所走出來的折線不能跨越x軸走到y=-1這條線上!在進行n次操作1和n此操作2後,此人必將到到達(2n,0)!若無跨越x軸的限制,折線的種數將為C(2n,n),即在2n次操作中選出n次作為操作1的方法數。

折線法

現在只要減去跨越了x軸的情況數。對於任意跨越x軸的情況,必有將與y=-1相交。找出第一個與y=-1相交的點k,將k點以右的折線根據y=-1對稱(即操作1與操作2互換了)。可以發現終點最終都會從(2n,0)對稱到(2n,-2)。由於對稱總是能進行的,且是可逆的。我們可以得出所有跨越了x軸的折線總數是與從(0,0)到(2n,-2)的折線總數。而後者的操作2比操作1要多0-(-2)=2次。即操作1為n-1,操作2為n+1。總數為C(2n,n-1)。

折線法

近日在複習資料結構,看到棧的時候,發現1個元素進棧,有1種出棧順序;2個元素進棧,有2種出棧順序;3個元素進棧,有5種出棧順序,那麼一個很自然地問題就是n個元素進棧,共有多少種出棧順序?

說來慚愧,以前學資料結構的時候竟然沒有考慮過這個問題。最近在看動態規劃,所以“子問題”這3個字一直在我腦中徘徊,於是解決這個問題的時候我也是用類似“子問題”的方法,說白了就是遞推公式。

我們把n個元素的出棧個數的記為f(n), 那麼對於1,2,3, 我們很容易得出:

f(1) = 1     //即 1

f(2) = 2    //即 12、21

                                     f(3) = 5

     //即 123、132、213、321、231

然後我們來考慮f(4), 我們給4個元素編號為a,b,c,d, 那麼考慮:元素a只可能出現在1號位置,2號位置,3號位置和4號位置(很容易理解,一共就4個位置,比如abcd,元素a就在1號位置)。

分析:

 1) 如果元素a在1號位置,那麼只可能a進棧,馬上出棧,此時還剩元素b、c、d等待操作,就是子問題f(3);

 2) 如果元素a在2號位置,那麼一定有一個元素比a先出棧,即有f(1)種可能順序(只能是b),還剩c、d,即f(2),     根據乘法原理,一共的順序個數為f(1) * f(2);

 3) 如果元素a在3號位置,那麼一定有兩個元素比1先出棧,即有f(2)種可能順序(只能是b、c),還剩d,即f(1),

    根據乘法原理,一共的順序個數為f(2) * f(1);

 4) 如果元素a在4號位置,那麼一定是a先進棧,最後出棧,那麼元素b、c、d的出棧順序即是此小問題的解,即         f(3);

結合所有情況,即f(4) = f(3) + f(2) * f(1) + f(1) * f(2) + f(3);

為了規整化,我們定義f(0) = 1;於是f(4)可以重新寫為:

f(4) = f(0)*f(3) + f(1)*f(2) + f(2) * f(1) + f(3)*f(0)

然後我們推廣到n,推廣思路和n=4時完全一樣,於是我們可以得到:

f(n) = f(0)*f(n-1) + f(1)*f(n-2) + ... + f(n-1)*f(0)

 

但這只是一個遞推公式(若程式設計實現,需要維護一個一維陣列,時間複雜度為O(n^2))。怎麼把它轉化為通項公式呢,複雜度僅為O(1)? 於是上網搜尋一下,原來真的有這麼一個公式: 現在的問題就是:怎麼從上述的遞推公式求出C(2n,n)/(n+1) ? 有興趣的朋友歡迎留言討論! //2013.6.4 update 根據網友u010896627的思路,我抽象了下問題,在知乎上問了個問題,其中有一個答案提出了“折現法”,從幾何上推出了“n個元素進棧有多少個出棧順序”這個問題的答案是C(2n,n)-C(2n,n-1),化簡一下即得Catalan number。推薦大家看一看。

相關推薦

資料結構_任意N元素有多少種順序(證明)

1.飯後,姐姐洗碗,妹妹把姐姐洗過的碗一個一個地放進碗櫥摞成一摞。一共有n個不同的碗,洗前也是摞成一摞的,也許因為小妹貪玩而使碗拿進碗櫥不及時,姐姐則把洗過的碗摞在旁邊,問:小妹摞起的碗有多少種可能的方式? 2.給定n個數,有多少種出棧序列? 3.一個有n個1和n個-1組成的字串,且前k個數的和均不小

n元素,輸出所有序列--遞迴

#include <iostream> #include <stack> #include <queue> #include <algorithm> #include <string.h> #include <

應用--n元素順序與從(0,0)到(n,n)不穿過對角線的方法

1.出棧順序方法數: hdoj1023 求出棧序列,比如1,2,3,出棧序列為3 2 1,1 2 3,1 3 2,2 1 3,2 3 1,一共5種 第一種思路: 我們把入棧看做1,出棧看做0,那麼入棧

【轉】【結構】【有n元素依次進,則序列有多少種】

排列 得到 掃描 思考 chm tails 應該 ext mark 卡特蘭數 大神解釋:https://blog.csdn.net/akenseren/article/details/82149145 權侵刪 原題 有一個容量足夠大的棧,n個元素以一定

N元素的進出總數-方法轉換-動態規劃

其實此題還可以用動歸方法解決,f[i,j],i表示入棧的個數,j表示出棧的個數,那f[i,j]就表示入棧i個數中出j個數的,但是此題要注意的是出棧數不能大於入棧數,那動歸方程該如何推導,再次謝謝一位某位具有探索精神的大神為我們做了細緻的研究現在我把它的論文貼上如下:

---n 元素順序,則可能的序列有多少種

題目:N個數依次入棧,出棧順序有多少種? 首先介紹一下卡特蘭數:卡特蘭數前幾項為 : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35

[原創]關於a1,a2,a3,...,an共n元素依次入其可能的排列的計算

以前一直以為1,2,3,4依次入棧可能出棧的順序只有一種,那就是4321,因為一直認為棧是先進後出的,所以.....,最後終於知道事實上在後面的元素入棧之前前面的元素可能會出棧,比如在4入棧之前321就已經依次出棧了,那出棧序列則為3214;那麼當每一個元素都滿足剛入棧就立即

N節點的二叉樹有多少種形態(

面試 誤區 樹的定義 節點 類型 基礎 更多 大於等於 證明 這是一道阿裏的面試題。其實算不上新鮮,但是我之前沒關註過,如今碰到了,就順便探討下這個問題吧:) 拿到這個題,首先想到的是直接寫出表達式肯定不行,所以有必要從遞推入手。由特殊到一般,歸納法麽~而且二叉樹離不開遞推

-N結點二叉樹個數

      N個結點二叉樹個數(不用卡特蘭數求解) 對於一個堆疊、若其入棧序列為1,2,3,……,n,不同的出入棧操作將產生不同的出棧序列。其出棧序列的個數正好等於結點個數為n的二叉樹的個數,且與不同形態的二叉樹一一對應。請簡要敘述一種從堆疊輸入(固定為1,2,3,……,n)/ 輸出序列對應一種二叉樹形

快速求第n模板

快速求第n位卡特蘭數 模板: 遞推法: /*通過遞推 求卡特蘭數的方法*/ #include<cstdio> #include<iostream> using names

n節點的二叉樹的種樹成的分佈

#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring&g

POJ2084 Game of Connections 關於經典的幾問題

可能 2個 nbsp 二叉樹 air sta memory poj 線段 Game of Connections Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9128 Accept

n對括號的匹配方式()

4對括號有多少種可能的合法匹配方式?n對括號呢? 此題是卡特蘭數的一個通常應用,相似的還有出棧順序等。關於卡特蘭數的具體內容,請參閱百度百科或Wiki. http://baike.baidu.com/view/2499752.htm   網路上可以搜到很多相關的題目和解答

[bzoj1485][HNOI2009]有趣的數列__組合數

有趣的數列 bzoj-1485 HNOI-2009 題目大意:求所有1~2n的排列滿足奇數項遞增,偶數項遞增。相鄰奇數項大於偶數項的序列個數%P。 註釋:$1\le n\le 10^6$,$1\le P \le 10^9$。 想法:好題啊。 我們依次考慮1~2n,就是把當前$i$放進奇數項還是偶數

n個數的方式(

問題 給定n個數,有多少種出棧序列,進棧是按照順序進棧? 分析:當n為1時: f(1) = 1 //即 1 當n為2時: f(2) = 2;//12, 21 當n為3

前100

留作備用 string catalan[]= { "1", "2", "5", "14", "42", "132", "429", "1430", "4862", "16796", "

------2行n列排隊問題

一、Catalan數的定義令h(1)=1,Catalan數滿足遞迴式:h(n) = h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1),n>=2該遞推關係的

資料結構連結串列 -- 查詢倒數第N元素、中間元素、建立連結串列

#include<iostream> using namespace std; typedef int Status; typedef int ElemType; #define OK 1 #define ERROR 0 #define MAXSIZE 10

從一個集合中查詢最大最小的N元素——Python heapq 堆資料結構

Top N問題在搜尋引擎、推薦系統領域應用很廣, 如果用我們較為常見的語言,如C、C++、Java等,程式碼量至少也得五行,但是用Python的話,只用一個函式就能搞定,只需引入heapq(堆佇列)這個資料結構即可。今天偶然看到這個庫,特意記下之。 先看一個例子: 複製

【學習點滴-資料結構-單鏈表】交換單鏈表中任意元素

/* * 演算法功能:建立單鏈表,交換單鏈表中的兩個元素。 * 演算法中的單鏈表是帶頭結點的。 * 函式說明:nop * @author:xiaoq-ohmygirl * @time :2012-06-20 **/ #include <stdio.h>