算法中的数学—卡特兰数(解析+代码实现)

算法中的数学—卡特兰数(解析+代码实现)总结一下碰到的关于卡特兰数的问题,方便后续复习。

大家好,又见面了,我是你们的朋友全栈君。

  卡特兰数又称卡塔兰数,是组合数学中一种常出现于各种计数问题中的数列。

一、简单介绍

  卡特兰数是一个数列,其前几项为(从第零项开始) : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …
卡特兰数满足如下递推关系:
在这里插入图片描述
其中 C n C_{n} Cn表示数列的第n项。根据上述第一个式子我们可以推出:
在这里插入图片描述
第二个推导式用于编程实现卡特兰数。

二、应用

2.1进出栈问题

【问题描述】
  1, 2, 3, 4依次进栈,则可能的一种进出栈顺序为:
1in->2in->2out->3in->4in->4out->3out->1out,所以出栈顺序为:2431,那么请问按照1, 2, 3, 4,…, n依次进栈,出栈顺序种数h(n)为多少?
【问题分析】
  对n个数,假设数k最后一个出栈,k有n种可能,即每一个数都有可能最后出栈,我们算出每一种可能各有多少种情况,最后相加即可。
  因为k最后一个出栈,而进栈顺序又是从小到大来的,所以k前面的k-1个数在k进栈以前就已经全部出栈了,我们把前面k-1个数看出一个整体,那么全面k-1个数的出栈情况实际上就有h(k-1)种。
  在k进栈之后,比k大的n-k个数才能进栈,但是它们又比k早出栈,把这n-k个数同样看成一个整体,共有h(n-k)种可能。 二者综合一下,当数k最后出栈时,一共有h(k-1)h(n-k)种可能,k从1取到n,再把每种可能相加即得到最终答案:
在这里插入图片描述
  简而言之就是数k把这段序列分成了两部分:比k大的部分和比k小的部分。因为中间有k隔着,而它们又必须按照从小到大的次序进栈,所以这两部分进出栈是相互不影响的。
  很明显可以看出,该表达式就是卡特兰数的递推式。

2.2排队方式

【问题描述】
  n个人手拿5元,n个人手拿10元,他们去排队买东西,东西价值5元,老板没有零钱(老板必须用收取的5元钞票给支付10元的顾客找零钱),请问一共有多少种排队方式?
【问题分析】
  将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈, 实际上也就转换成了进出栈问题,答案也为h(n)。

2.3二叉树生成问题

【问题描述】
  有n个结点,请问总共能构成多少种不同的二叉树?
【问题分析】
  假设采用中序遍历,根节点第k个被访问,则根的左子树共有k-1个结点,右子树共有n-k个结点,k同样可以取1-n,这就与进出栈问题分析思路一致了,所以一共h(n)种。

2.4凸多边形三角形划分

【问题描述】
  一个凸的n边形,用直线连接它的两个顶点使之分成多个三角形,每条直线不能相交,问一共多少种方案?
比如凸六边形的划分情况为:
在这里插入图片描述
h(6)=14。
【问题分析】
  我们将凸多边形顶点从p1一直编号到pn,以p1pn这条边为基准,任选一个数k(2<=k<=n-1),将p1,pk以及pn三点连接,构成了一个三角形。该三角形把该凸边形划分成了两个凸边形,一边顶点为1 ~ k-1,另一边为k+1 ~ n,于是又回到了进出栈问题,所以答案依旧为:h(n)。

2.5括号匹配问题

【问题描述】
由1对括号,可以组成一种合法括号序列:()。
由2对括号,可以组成两种合法括号序列:()()、(())。
由n对括号组成的合法括号序列一共有多少种?
【问题分析】
  考虑n对括号时的任意一种配对方案,最后一个右括号有唯一的与之匹配的左括号,于是有唯一的表示A(B),其中A和B也是合法的括号匹配序列。
  假设S(n)为n对括号的正确配对数目,那么有递推关系S(n)=S(0)S(n-1)+S(1)S(n-2) +…+S(n-1)S(0),显然S(n)是卡特兰数。

2.6满二叉树个数

【问题描述】
  n+1个叶子的满二叉树个数为多少?
【问题分析】
  不再分析,答案为h(n)。

2.7圆划分问题

【问题描述】
  在圆上选2n个点,讲这些点成对连接起来,保证所有直线不相交,问一共多少种可能?
【问题分析】
  答案为h(n)。

2.8填充问题

【问题描述】
  n个长方形填充一个高度为n的阶梯状图像方法数为多少?
【问题分析】
  答案为h(n)。

代码实现:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;

const int maxn = 20;
int n;
ll f1[maxn], f2[maxn];
ll f[maxn * 2][maxn];

//公式1:
int solve1() { 
   
    f1[0] = f1[1] = 1;
    cin >> n;
    for(int i = 2; i <= n; i++) { 
   
        for(int j = 0; j < i; j++) { 
   
            f1[i] += (f1[j] * f1[i-j-1]);   //f(n)=f(0)f(n-1)+f(1)f(n-2)+...+f(n-1)f(0) 
        }
    }
    printf("%lld\n",f1[n]);
    return 0;
}

//公式2:
int solve2() { 
   
    f2[0] = f2[1] = 1;
    cin >> n;
    for(int i = 2; i <= n; i++)
    { 
   
        f2[i] += f2[i - 1] * (4 * i - 2) / (i + 1);  //f(n)=f(n-1)*(4*n-2)/(n+1)
    }
    printf("%lld\n", f2[n]);
    return 0;
}

//公式3:
int solve3() { 
   
	cin >> n;
    for(int i = 1; i <= 2 * n; i++) { 
   
        f[i][0] = f[i][i] = 1;
        for(int j = 1; j < i; j++) { 
   
            f[i][j] = f[i - 1][j] + f[i - 1][j - 1];     //f(n)=c(2n,n)/(n+1)
        }
    }
    printf("%lld",f[2 * n][n] / (n + 1));
    return 0;
}

int main() { 
   
	solve1();
	solve2();
	solve3();
	return 0;
} 

  欢迎大家关注我的微信公众号:KI的算法杂记,有什么问题可以直接发私信。

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132277.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • django通用视图通俗讲解_视图的种类通常有

    django通用视图通俗讲解_视图的种类通常有前言上篇我们通过mixin可以非常方便的实现一些CURD操作。实际上针对这些mixin,DRF还进一步的进行了封装,放到generics下。有以下generic类视图:generics.ListA

    2022年8月7日
    5
  • php中接口、抽象类以及接口和抽象类区别详解

    php中接口、抽象类以及接口和抽象类区别详解php中接口、抽象类以及接口和抽象类区别详解

    2022年4月24日
    44
  • html2canvas, JsPDF生成pdf

    html2canvas, JsPDF生成pdf创建 pdf js 引入依赖 importVuefro vue importhtml2c html2canvas importJsPDFf jspdf constPDF PDF install function Vue options targetDom 需要打印的 dom 对象 name pdf 的名字 callback 回调函数 Vue prototype create

    2025年7月12日
    3
  • log4j使用方法_altium16详细使用教程

    log4j使用方法_altium16详细使用教程日志是应用软件中不可缺少的部分,Apache的开源项目Log4j是一个功能强大的日志组件,提供方便的日志记录。在apache网站:jakarta.apache.org/log4j可以免费下载到Log4j最新版本的软件包。

    2025年9月15日
    5
  • 一篇文章彻底搞懂异步,同步,setTimeout,Promise,async「建议收藏」

    一篇文章彻底搞懂异步,同步,setTimeout,Promise,async「建议收藏」之前翻看别的大佬的博客看到了关于setTimeout,promise还有async执行顺序的文章。观看了几篇之后还是没有怎么看懂,于是自己开始分析代码,并整理了此文章,我相信通过此文章朋友们能对异步同步还有,setTimeout,Promise,async这些内容了然于胸,接下来让我们走入正题:…

    2022年7月12日
    18
  • wing是什么_acwing是什么

    wing是什么_acwing是什么原题链接设有 N×N 的方格图,我们在其中的某些方格中填入正整数,而其它的方格中则放入数字0。如下图所示:某人从图中的左上角 A 出发,可以向下行走,也可以向右行走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。此人从 A 点到 B 点共走了两次,试找出两条这样的路径,使得取得的数字和为最大。输入格式第一行为一个整数N,表示 N×N 的方格图。接下来的每行有三个整数,第一个为行号数,第二个为列号数,第三个为在该行、该列上所放的数。行和列编号从

    2022年8月8日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号