• 卡特兰数问题


    今天看到去年的微软笔试题其中有一道是,进栈出栈的题目,给定1,2,。。。n共n个数,问有多少种不同的出栈次序?

    我的第一直觉就是这个东西很熟悉,应该是卡特兰数问题,当然事实上也是如此,下面是更严密的分析:

    将每个数的进栈操作标记为状态‘1’,出栈操作标记为状态‘-1’,对于栈来讲,肯定是进栈的次数大于等于出栈的次数(因为不可能还没进去呢就能出来)

    于是,就是状态序列中1的个数大于-1的个数的问题,这正是卡特兰数问题,也就是任何时刻所有状态序列中所有标记之和都要大于等于0。

    题目一下子变得很简单,结果就是C(2n,n)/(n+1).

    下面给出卡特兰数的定义:

    令h(1)=1,h(0)=1,catalan数(卡特兰数)满足递归式:

      h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2)

      另类递归式:

      h(n)=((4*n-2)/(n+1))*h(n-1);

      该递推关系的解为:

      h(n)=C(2n,n)/(n+1) (n=1,2,3,...)

    其实卡特兰数是非常有用的一个东西,而且非常有意思,下面举几个常见的例子:

    1、给定节点组成二叉树个数有多少?

    分析:

    当n=1时,只有1个根节点,则只能组成1种形态的二叉树,令n个节点可组成的二叉树数量表示为h(n),则h(1)=1; h(0)=0;

    当n=2时,1个根节点固定,还有2-1个节点。这一个节点可以分成(1,0),(0,1)两组。即左边放1个,右边放0个;或者左边放0个,右边放1个。即:h(2)=h(0)*h(1)+h(1)*h(0)=2,则能组成2种形态的二叉树。

     当n=3时,1个根节点固定,还有2个节点。这2个节点可以分成(2,0),(1,1),(0,2)3组。即h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=5,则能组成5种形态的二叉树。

    以此类推,当n>=2时,可组成的二叉树数量为h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)*h(0)种,即符合Catalan数的定义,可直接利用通项公式得出结果。

    2、矩阵链乘法问题(加括号问题)(此处只求种类树,不是求最优问题)

    分析:给定n个矩阵{A1,A2,...An},其中Ai与Ai+1是可乘的,考查这n个矩阵的乘积A1A2...An,使得所需的数乘次数最少。

    设n个矩阵的连乘有不同的计算次序P(n),可以先在第k个和第k+1个矩阵之间讲原矩阵分为两个矩阵子序列,k=1,2,...n-1。然后分别对这两个矩阵子序列完全加括号;

    最后对所得的结果加括号,得到原矩阵序列的一个完全加括号,得递归式

    n=1 时 P(n)=1;

    n>1 时 P(n)=∑ k=1~n-1(P(k)*P(n-k));

    P(n)就是卡特兰数这么多种计算次序,如果用穷举法查找数乘次数最小需要P(n)次运算,因此该问题可以用动态规划来求解(这不是本文要叙述的重点)

    3、凸多边形三角划分问题(最优解用到动态规划算法,此处只求划分种树)

    分析:
    在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形。现在的任务是键盘上输入凸多边形的边数n,求不同划分的方案数f(n)。
    比如当n=6时,f(6)=14。
     
    如果纯粹从f(4)=2,f(5)=5,f(6)=14,……,f(n)=n慢慢去归纳,恐怕很难找到问题的递推式,我们必须从一般情况出发去找规律。
    因为凸多边形的任意一条边必定属于某一个三角形,所以我们以某一条边为基准,以这条边的两个顶点为起点P1和终点Pn(P即Point),将该凸多边形的顶点依序标记为P1、P2、……、Pn,再在该凸多边形中找任意一个不属于这两个点的顶点Pk(2<=k<=n-1),来构成一个三角形,用这个三角形把一个凸多边形划分成两个凸多边形,其中一个凸多边形,是由P1,P2,……,Pk构成的凸k边形(顶点数即是边数),另一个凸多边形,是由Pk,Pk+1,……,Pn构成的凸n-k+1边形。
     
    总而言之,卡特兰数非常有用。
  • 相关阅读:
    后端框架:SpringBoot+Mybatis+Dubbox(zookeeper+dubbo-admin)
    java代码执行mysql存储过程
    SpringBoot整合Junit
    摘要算法之MD5
    java如何控制下载的文件类型是txt还是doc?如何将文件名返回给前端?Content-disposition
    Android Atuido 连接模拟器
    verilog CRC 校验
    Altium Designer(AD软件)如何导出gerber文件
    SpringBoot集成mybatisplus
    C++ | 通过智能指针实现资源管理
  • 原文地址:https://www.cnblogs.com/taotao315/p/3000755.html
Copyright © 2020-2023  润新知