卡特兰数--
卡特兰数(Catalan Number)
Go 语言动态规划实现
func Catalan(n int) int {dp := make([]int, n+1)dp[0] = 1dp[1] = 1for i := 2; i <= n; i++ {for j := 1; j <= i; j++ {dp[i] += dp[j-1]*dp[i-j]}}return dp[n]
}
🎯 卡特兰数的动态规划递推公式
🔁 递推公式(动态规划版)
卡特兰数满足以下递推关系:
C₀ = 1
Cₙ = C₀×Cₙ₋₁ + C₁×Cₙ₋₂ + C₂×Cₙ₋₃ + ... + Cₙ₋₁×C₀
也可以写作:
Cₙ = ∑ (Cᵢ × Cₙ₋₁₋ᵢ),其中 i 从 0 到 n-1
应用场景
1. 括号匹配问题
在一个合法的括号序列中:
-
左右括号数量相等;
-
任意位置,左括号数量不少于右括号。
例如:
-
合法:
()
,(())
,()()
; -
非法:
())
,()))(()
。
n 对括号的合法排列数是第 n 个卡特兰数。
2. 出栈序列问题
假设一个栈初始为空,有 n 个元素依次入栈。
不同的出栈序列数量为第 n 个卡特兰数。
例如:当 n = 3 时,元素 1, 2, 3 入栈,可能的出栈序列有:
-
123
-
132
-
213
-
231
-
321
共 5 种,即 C₃ = 5。
3. 二叉树形态问题(二叉搜索树同样适用)(对于二叉搜索树):节点带有唯一编号(1~n)
由 n 个节点构成的不同形态的二叉树数量为第 n 个卡特兰数。
例如:当 n = 3 时,有 5 种不同形态的二叉树。
4. 凸多边形的三角剖分问题
将一个凸 n+2 边形,用 n−1 条不相交对角线划分成 n 个三角形。
剖分方法数为第 n 个卡特兰数。
例如:当 n = 3(对应五边形),有 5 种三角剖分方法。
5. 路径问题(Dyck Path)
在 n×n 方格上,从左下角走到右上角:
-
只能向右或向上走;
-
且不能穿过对角线。
满足条件的路径数量为第 n 个卡特兰数。
例如:当 n = 3 时,有 5 条合法路径。
6. 矩阵乘法运算顺序问题
对 n 个矩阵 A₁A₂…An,根据结合律加括号,不改变顺序:
不同的乘法顺序数为第 n−1 个卡特兰数。
例如:A₁A₂A₃A₄ 的括号组合方式有:
-
(A₁(A₂(A₃A₄)))
-
(A₁((A₂A₃)A₄))
-
((A₁A₂)(A₃A₄))
-
((A₁(A₂A₃))A₄)
-
(((A₁A₂)A₃)A₄)
共 5 种,即 C₃ = 5。
7. 圆上点连线问题
在圆上选择 2n 个点,两两连线且不允许线段相交。
不同连线方式数量为第 n 个卡特兰数。
例如:n = 3(6 个点)时,有 5 种不相交连线方法。
8. 投票顺序问题
有 2n 个人投票,其中 n 票赞成、n 票反对。
要求:投票过程中任意时刻赞成票不少于反对票。
满足条件的投票顺序数为第 n 个卡特兰数。
例如:n = 3 时,合法顺序包括:
-
赞成赞成赞成反对反对反对
-
赞成赞成反对赞成反对反对
-
等等,共 5 种。
9. 正则表达式的合法匹配树结构
将正则表达式转换为语法树时,不同的合法匹配结构数量为第 n 个卡特兰数。
例如:对于带有 |
(或)、*
(重复)、括号等结构的正则,其合法解析方式的总数可用卡特兰数计数。
10. AVL 树构建数量(高度平衡二叉树)
给定 n 个节点,构建满足 AVL 高度平衡条件的二叉树的方案数,在某些简化条件下也呈现卡特兰数的增长趋势。
虽然不是完全等价,但当我们限制树高度差时,其子问题的递推方式与卡特兰数类似。
11. 全括号表达式(完全二叉运算树)
对于形如 a * b * c * d
的操作数序列,在不改变操作数顺序的前提下,通过加括号来确定乘法顺序的方式有 n-1 个卡特兰数种。
例如,对于 a * b * c * d
:
-
((a * (b * (c * d))))
-
(a * ((b * c) * d))
-
((a * b) * (c * d))
-
(((a * b) * c) * d)
-
((a * (b * c)) * d)
共 5 种,即 C₃ = 5。
12. 单调栈中构造不下降子序列的方式
在使用栈构造特定不下降子序列(如栈排序问题)时,某些构造路径数也可以转化为卡特兰数的问题。
这类问题通常是判断合法出栈序列、不交叉子序列或序列递归划分,其本质与卡特兰数的组合结构密切相关。