[棧] 卡特蘭數(shù)與入棧出棧序列

假如現(xiàn)在有這么一個問題:

一個序列從1到n依次入棧, 那么可能的出棧序列一共有多少種?
注意: 在任意一個時刻,只要棧不為空, 就可能有元素出棧, 不是說元素全部入棧之后再出棧

這個問題的解其實(shí)等同于求n階的卡特蘭數(shù)(catalan)

先給出問題的解
設(shè)n階的卡特蘭數(shù)為k(n), 那么

k(0) = 1, k(1) = 1

k(n) = k(0) * k(n - 1) + k(1) * k(n - 2) + ... + k(n - 2) * k(1) + k(n - 1) * k(0)
或者
k(n) = c(2n, n) / (n + 1)
或者
k(n) = c(2n, n) - c(2n, n-1)

下面是問題的具體分析過程

首先說明為什么問題的解是卡特蘭數(shù)

卡特蘭數(shù)指的是在一個n*n的方格中,從左下角走到右上角. 每一步只能往右或者往上, 且在走的過程中不能越過從左下角到右上角的那條對角線.

和入棧出棧問題對比可以發(fā)現(xiàn), 這里的往右走就相當(dāng)于入棧, 往上走就相當(dāng)于出棧, 對角線上的點(diǎn)就相當(dāng)于棧為空的時候, 不能越過對角線就是說在棧為空的時候不能執(zhí)行彈棧操作

那么卡特蘭數(shù)如何求得呢, 思路有很多,這里說幾種比較容易理解的

1. 用排列組合的方法來求

我們借助棧的思想來理解

n個元素入棧再出棧, 那么就有 2n 次操作, 正常情況下是n次入棧操作, n次出棧操作, 根據(jù)排列組合的方法, 共有 c(2n, n) 種可能性

當(dāng)然了,在這 c(2n, n) 種可能性中, 肯定是有非法操作的, 也就是在在為空或者為負(fù)的時候進(jìn)行出棧操作, 那么非法的情況一共有多少種呢?

我們假設(shè)在第一次出現(xiàn)非法操作的時候, 這個時候棧中元素個數(shù)為 -1 , 因?yàn)樵跊]有元素的時候進(jìn)行了出棧操作. 由于最終棧中元素?cái)?shù)量為 0 , 那么在這一步之后的操作中,入棧次數(shù)肯定比出棧次數(shù)多 1 . 如果我們對這次操作之后的所有操作進(jìn)行反轉(zhuǎn), 那么最終棧中元素的數(shù)量就是 -1 減去 1 = -2 了. 這就是非法的情況.

在非法的情況下, 由于最終棧中元素?cái)?shù)為-2, 所以在2n次操作中, 肯定有 n - 1 次入棧操作, n + 1 次出棧操作. 這時入棧次數(shù)和出棧次數(shù)不同是因?yàn)槲覀儗Σ糠植僮鬟M(jìn)行了反轉(zhuǎn), 這一點(diǎn)要明白.

到這里, 答案就很明顯了, 非法操作的次數(shù)為 c(2n, n -1) = c(2n, n + 1)

所以合法的次數(shù)等于所有可能的次數(shù)減去非法的次數(shù), 即:

k(n) = c(2n, n) - c(2n, n-1)

2. 折線法

這種方法其實(shí)與第一種方法有異曲同工之妙, 只是運(yùn)用了圖形來幫助理解

我們假設(shè)一個人在原點(diǎn)汉买,操作1是此人沿右上角45°走一個單位(一個單位設(shè)為根號2,這樣他第一次進(jìn)行操作1就剛好走到(1,1)點(diǎn))佩脊,操作2是此人沿右下角45°走一個單位蛙粘。第k次操作2前必須先進(jìn)行至少k次操作1,就是說明所走出來的折線不能跨越x軸走到y(tǒng)=-1這條線上威彰!在進(jìn)行n次操作1和n此操作2后出牧,此人必將到到達(dá)(2n,0)歇盼!若無跨越x軸的限制舔痕,折線的種數(shù)將為 c(2n,n),即在 2n 次操作中選出n次作為操作1的方法數(shù)赵讯。

合法情況.jpg

現(xiàn)在只要減去跨越了x軸的情況數(shù)盈咳。對于任意跨越x軸的情況,必有將與 y = -1相交边翼。找出第一個與 y = -1 相交的點(diǎn) k,將k點(diǎn)以右的折線根據(jù) y = -1 對稱(即操作1與操作2互換了)鸣剪∽榈祝可以發(fā)現(xiàn)終點(diǎn)最終都會從(2n,0)對稱到(2n筐骇,-2)债鸡。由于對稱總是能進(jìn)行的,且是可逆的铛纬。我們可以得出所有跨越了x軸的折線總數(shù)是與從(0,0)到(2n,-2)的折線總數(shù)厌均。而后者的操作2比操作1要多 0-(-2)=2次。即操作 1 為 n-1 , 操作 2 為 n+1告唆」妆祝總數(shù)為 c(2n,n-1)擒悬。

非法情況.jpg

3. 遞歸的方法

若用(n模她,m)表示有n個元素還沒有入棧,棧內(nèi)目前有m個元素時懂牧,出棾蘧唬可能的種數(shù)。則問題就是(n僧凤,0)畜侦。

當(dāng)目前狀態(tài)為(n, 0)時只能進(jìn)行入棧操作,則有(n, 0) = (n - 1, 1)躯保。當(dāng)m>=1時旋膳,可以入棧也可以出棧則有(n, m) = (n - 1, m + 1) + (n, m - 1)。顯然(0, m) = 1吻氧。這樣就有了終止條件溺忧。

以上思路可以用遞歸程序?qū)崿F(xiàn)

function catalan(n)
{
    return condition(n, 0)
}

/*
 * 遞歸函數(shù), 用來求特定的某個時刻對應(yīng)的可能性種數(shù)
 *
 * @param total - 還沒有入棧的元素的個數(shù)
 *
 * @param inStack - 當(dāng)前棧中元素個數(shù)
 *
 */
function condition(outStack, inStack)
{
    if(outStack === 0)
    {
        return 1
    }
    if(inStack === 0)
    {
        return condition(outStack - 1, 1)
    }
    return condition(outStack - 1, inStack + 1) + condition(outStack, inStack - 1)
    // 注意, 這里第二項(xiàng)inStack減少1然而outStack沒有加1是因?yàn)檫@個出棧的元素已經(jīng)不必再考察了, 我們
    // 只需要關(guān)注后面的還沒有入棧元素即可
}

// 測試

for(let i = 1; i <= 10; i ++)
{
    console.log(`${i}階卡特蘭數(shù)為: ${catalan(i)}`)
}

// 1階卡特蘭數(shù)為: 1
// 2階卡特蘭數(shù)為: 2
// 3階卡特蘭數(shù)為: 5
// 4階卡特蘭數(shù)為: 14
// 5階卡特蘭數(shù)為: 42
// 6階卡特蘭數(shù)為: 132
// 7階卡特蘭數(shù)為: 429
// 8階卡特蘭數(shù)為: 1430
// 9階卡特蘭數(shù)為: 4862
// 10階卡特蘭數(shù)為: 16796
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盯孙,隨后出現(xiàn)的幾起案子鲁森,更是在濱河造成了極大的恐慌,老刑警劉巖振惰,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歌溉,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)痛垛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門草慧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人匙头,你說我怎么就攤上這事漫谷。” “怎么了蹂析?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵舔示,是天一觀的道長。 經(jīng)常有香客問我电抚,道長惕稻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任蝙叛,我火速辦了婚禮俺祠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘借帘。我一直安慰自己蜘渣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布姻蚓。 她就那樣靜靜地躺著宋梧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狰挡。 梳的紋絲不亂的頭發(fā)上捂龄,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機(jī)與錄音加叁,去河邊找鬼倦沧。 笑死,一個胖子當(dāng)著我的面吹牛它匕,可吹牛的內(nèi)容都是我干的展融。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼豫柬,長吁一口氣:“原來是場噩夢啊……” “哼告希!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起烧给,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤燕偶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后础嫡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體指么,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酝惧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了伯诬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晚唇。...
    茶點(diǎn)故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖盗似,靈堂內(nèi)的尸體忽然破棺而出哩陕,到底是詐尸還是另有隱情,我是刑警寧澤赫舒,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布萌踱,位于F島的核電站,受9級特大地震影響号阿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸳粉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一扔涧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧届谈,春花似錦枯夜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至曙搬,卻和暖如春摔吏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纵装。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工征讲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人橡娄。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓诗箍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挽唉。 傳聞我的和親對象是個殘疾皇子滤祖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容