卡特蘭數的概念
假如現在有這么一個問題:
一個序列從1到n依次入棧,那么可能的出棧序列一共有多少種?
注意:在任意一個時刻,只要棧不為空,就可能有元素出棧,不是說元素全部入棧之后再出棧。
這個問題的解其實等同於求n階的卡特蘭數(catalan)
卡特蘭數指的是在一個n*n的方格中,從左下角走到右上角。每一步只能往右或者往上,且在走的過程中不能越過從左下角到右上角的那條對角線。
和入棧出棧問題對比可以發現,這里的往右走就相當於入棧,往上走就相當於出棧,對角線上的點就相當於棧為空的時候, 不能越過對角線就是說在棧為空的時候不能執行彈棧操作。
出棧序列的求解方法
既然往右相當於入棧, 往上相當於出棧,那么從左下角到右上角的路徑即為對應的入棧出棧操作序列,我們可以執行全部的操作序列來獲取全部的出棧序列。所以求解出棧序列的個數,只需求出搜索路徑有多少個。
當棧深度為4時,所有可能的搜索路徑(入棧出棧操作序列):
那么搜索又要如何實現?
首先合理的搜索需要滿足兩個前提:
- 每一步只能往右或者往上
- 且在走的過程中不能越過從左下角到右上角的那條對角線
搜索的遞歸實現:
- 從某點開始的后續搜索,可以由其上方點的后續搜索和其右方點的后續搜索組成。
#include <stdio.h>
#include <stdlib.h>
void catalan(int push, int pop, int n, char *order) {
int index = push + pop;
if (push == pop && pop == n) {
order[index] = '\0';
printf("%s\n", order);
}
if (push < n) {
order[index] = 'i';
catalan(push + 1, pop, n, order);
}
if (pop < push) {
order[index] = 'o';
catalan(push, pop + 1, n, order);
}
}
int main() {
// n個數入棧
int n;
scanf("%d", &n);
// 入棧出棧操作序列長為2n;
char *order = calloc(2 * n + 1, sizeof(char));
// 輸出所有的入棧出棧操作序列
catalan(0, 0, n, order);
free(order);
return EXIT_SUCCESS;
}
參考鏈接