卡特兰数

C(n) = C(0)C(n-1) + C(1)C(n-2) + ... + C(n-1)C(0)
或者C(n) = (2n)! / (n!
(n+1)!)
C(0) = C(1) = 1
满足这样条件的序列就是卡特兰数。

  1. 1到n的整数能构建多少不同的BST(binary search tree)?
    任一个整数做根节点时,其左右BST子树的个数乘积就是这个整数做根节点的BST的个数,而1到n任一个整数做根节点的子树的个数相加,就是该问题的答案。例如:设该问题的解为h(n), 1做根节点,则左子树不可能有节点,而2~n共n-1个节点构成了右子树,所以BST个数是h(0)h(n-1), k做根节点,则左子树只能有k-1个节点,而右子树只能有n-k个节点,此时BST个数是h(k-1)h(n-k), 综上, h(n) = h(0)h(n-1) + h(1)h(n-2) + ... + h(k-1)h(n-k) + ... + h(n-1)h(0)。可以看出该问题的答案实际上就是求解卡特兰数
  2. 设有无穷大的栈,已知入栈序列为1,2,...,n,求所有可能的出栈序列的个数
    假设最后一个出栈的元素是k, 1 <= k <= n, 则显然在k入栈之前,1到k-1已经全部出栈了;而在k入栈后,k+1到n开始入栈,并在k出栈前全部出栈完毕。设该问题的解是h(n), 则显然当最后一个出栈的元素是k时,左右可能的出栈序列是h(k-1)h(n-k),
    而h(n) = h(0)
    h(n-1) + h(1)h(n-2) + ... + h(k-1)h(n-k) + ... + h(n-1)*h(0)。可以看出该问题的答案实际上也是求解卡特兰数。
  3. 有n对(),求所有可能的括号序列个数,比如n = 2时(()), ()()
    我们可以把'('看成入栈,')'看成出栈,所以问题3实际上就等同于问题2
  4. 有2n个人买票,票价是5元,n个人有5元,n个人有10元,剧场没有零钱,有多少种可能排队,可以让所有人都买到票。
    我们可以吧5元看成入栈,10元看成出栈,所以问题4实际上就等同于问题2

问题2还可以用另一种角度来看,假设1代表入栈,0代表出栈,在2n位二进制数中填入n个1的方案数为c(2n,n),不填1的其余n位自动填0。从中减去不符合要求(由左而右扫描,0的累计数大于1的累计数)的方案数即为所求。
不符合要求的数的特征是由左而右扫描时,必然在某一奇数位2m+1位上首先出现m+1个0的累计数和m个1的累计数,此后的2(n-m)-1位上有n-m个 1和n-m-1个0。如若把后面这2(n-m)-1位上的0和1互换,使之成为n-m个0和n-m-1个1,结果得1个由n+1个0和n-1个1组成的2n位数,即一个不合要求的数对应于一个由n+1个0和n-1个1组成的排列。
反过来,任何一个由n+1个0和n-1个1组成的2n位二进制数,由于0的个数多2个,2n为偶数,故必在某一个奇数位上出现0的累计数超过1的累计数。同样在后面部分0和1互换,使之成为由n个0和n个1组成的2n位数,即n+1个0和n-1个1组成的2n位数必对应一个不符合要求的数。
因而不合要求的2n位数与n+1个0,n-1个1组成的排列一一对应。
显然,不符合要求的方案数为c(2n,n+1)。由此得出输出序列的总数目=c(2n,n)-c(2n,n+1)=c(2n,n)/(n+1)=h(n)。

public class Solution {
    static void parenthese(String currentSeq, int leftLNum, int leftRNum) {
        if (leftRNum == 0) {
            System.out.println(currentSeq);
            return;
        }
        if (leftLNum == 0) {
            for (int i = 0; i < leftRNum; i++) {
                currentSeq += ")";
            }
            System.out.println(currentSeq);
            return;
        }
        if (leftLNum == leftRNum) {
            parenthese(currentSeq + "(", leftLNum - 1, leftRNum);
        } else {
            parenthese(currentSeq + "(", leftLNum - 1, leftRNum);
            parenthese(currentSeq + ")", leftLNum, leftRNum - 1);
        }
    }
    public static void parenthese(int n) {
        parenthese("", n, n);
    }
    static void printStack(final String seq) {
        int oneCount = 0;
        int zeroCount = 0;
        for (int i = 0; i < seq.length(); i++) {
            if (seq.charAt(i) == '1') {
                oneCount++;
            } else {
                if (seq.charAt(i - 1) == '1') {
                    System.out.print(oneCount);
                    zeroCount = 0;
                } else {
                    System.out.print(oneCount - zeroCount);
                }
                zeroCount++;
            }
        }
        System.out.print("\n");
    }
    static void stack(String currentSeq, int leftPushNum, int leftPopNum) {
        if (leftPopNum == 0) {
            printStack(currentSeq);
            return;
        }
        if (leftPushNum == 0) {
            for (int i = 0; i < leftPopNum; i++) {
                currentSeq += "0";
            }
            printStack(currentSeq);
            return;
        }
        if (leftPushNum == leftPopNum) {
            stack(currentSeq + "1", leftPushNum - 1, leftPopNum);
        } else {
            stack(currentSeq + "1", leftPushNum - 1, leftPopNum);
            stack(currentSeq + "0", leftPushNum, leftPopNum - 1);
        }
    }
    public static void stack(int n) {
        stack("", n, n);
    }
    public static void main(String[] argc) {
        parenthese(4);
        stack(4);
    }
}

参考阅读

求所有可能出栈序列
判断出栈序列是否合法
卡特兰数_百度百科
从《编程之美》买票找零问题说起
Unique Binary Search Trees

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了...
    mylocal阅读 612评论 0 0
  • 首先来自百度百科Q:一个栈(无穷大)的[进栈]序列为1,2,3,…,n,有多少个不同的[出栈]序列?A1:首先,我...
    shuff1e阅读 357评论 0 0
  • 假如现在有这么一个问题: 一个序列从1到n依次入栈, 那么可能的出栈序列一共有多少种?注意: 在任意一个时刻,只要...
    爱上落入尘世间的你阅读 4,690评论 0 10
  • 定义 1.卡特兰数是一种数列,以比利时的数学家欧仁·查理·卡塔兰命名。2.卡特兰数列:1, 1, 2, 5, 14...
    面包牛奶wlq阅读 2,513评论 0 2
  • 我游离在你的屋旁 时不时伫足仰望 心想那是不是你的倩影 倒映在你的帘,动乱了你的窗 我游离在你的屋旁 走不走又在心里掂量
    比勒罕阅读 164评论 0 1