C++ 组合数2025年3月17日 | 阅读 7 分钟 引言卡特兰数 也可以明确地定义为自然数序列,它们出现在许多计数问题中:有效括号表达式的数量、二叉搜索树的数量、网格中的路径数量等等。它们以十九世纪中叶的比利时数学家 Eugène Charles Catalan 的名字命名。它以 1, 1, 2, 5, 14, 42 等开始。 在 C++ 中,有两种方法可以解决卡特兰数问题:使用递归或使用动态规划。递归方法遵循上述递归关系,但由于重复计算,在输入较大时可能效率不高。然而,动态规划会保存已计算的结果,因此不必一次又一次地计算相同的内容,这使其更有效率。通过使用数组或向量等简单数据结构并实现阶乘运算,您可以轻松地在 C++ 中实现卡特兰数的生成。与任何问题解决算法一样,在 C++ 中应用这些数字的技能可以提高在不同组合问题中的解决问题的能力。 卡特兰数的数学概念卡特兰数是自然数的多项式,在组合数学的许多领域都有应用。第 n 个卡特兰数,记作 Cn,由以下公式给出: ![]() 其中 (2nn) 表示二项式系数。该公式表示正确匹配 n 对括号的方法数,以及其他组合结构。 递推关系 卡特兰数也可以递归定义为: ![]() 基例为 C0=1 示例输入: n = 6 输出 132 输入: n = 8 输出 1430 程序 1 我们来看一个使用动态规划计算第 n 个卡特兰数的 C++ 程序。 输出 Enter the value of n: 6 The 6th Catalan number is: 132 说明
程序 2我们来看另一个使用递归编程计算第 n 个卡特兰数的 C++ 程序。 输出 Enter the value of n: 8 The 8th Catalan number is: 1430 === Code Execution Successful === 说明
递归的问题
相比之下,动态规划版本运行时间为 O(n2),对于较大的 n 效率更高。 动态规划和递归编程的复杂度分析1. 递归方法复杂度在递归方法中,使用以下公式计算卡特兰数 Cn: 每次计算 n 的值时,函数都会对下一个较小值 n 调用两次。这会导致多次重新计算较小的卡特兰数,从而使时间复杂度呈指数级增长。
2. 动态规划方法复杂度在动态规划方法中,卡特兰数的计算无需重新计算所有值,而是将结果存储在数组中以供以后使用。公式保持不变,但值是按降序计算的。 对于每个 Cn,计算包括将通过乘以 Ci * Cn-i-1 获得的一个数字相加。该总和包含 n 个项,并且所有上述过程都为 n = 0, 1, 2, ...., n 进行迭代。
复杂度总结
卡特兰数的应用卡特兰数出现在广泛的组合问题中,并在数学和计算机科学的不同领域有许多应用。以下是一些最常见的卡特兰数应用: 1. 有效括号表达式(平衡括号)卡特兰数计算正确匹配 nnn 对括号的方法数。例如,对于 n=3n = 3n=3,有效的组合是:
2. 二叉搜索树 (BST)第 n 个卡特兰数是您可以将 n 个不同元素放入有序列表中的方法数。这在搜索算法和数据库索引问题中尤为重要。 3. 凸多边形三角剖分具有 n+2 条边的凸多边形的三角剖分方法数等于使用 n 个不同节点的第 n 个卡特兰数。这对于优化搜索算法和数据库索引很有用。 4. 网格中的路径卡特兰数计算从 n×n 网格的左下角到右上角移动的方法数,只采取向右和向上的步骤,同时从不越过对角线。 5. 非交叉握手如果 2n 个人围成一圈坐着,形成 n 次握手而不交叉的方法数是卡特兰数。这个问题也可以在弦图的背景下看到。 6. 迪克路径迪克路径是从 (0,0) 到 (n,n) 的格子路径,且从不低于 y=x 线。n 步的此类路径数由第 n 个卡特兰数给出。 7. 山峦卡特兰数计算绘制具有 n 个峰的山峦的方法数,其中每个山都从海平面开始并回到海平面,且没有两个山重叠。 8. 非交叉分区卡特兰数计算将 n 个元素的集合划分为非交叉子集的方法数,其中没有子集的连接会相互交叉。 9. 堆栈排序问题卡特兰数计算可以使用堆栈排序的 1,2,...,n 的排列数(称为“堆栈可排序排列”)。 10. 满二叉树第 n 个卡特兰数计算具有 n 个内部节点的满二叉树的数量,其中每个内部节点恰好有两个子节点。 结论总之,卡特兰数是组合学中的一个基本序列,为广泛的计数问题提供了解决方案,包括有效括号表达式、二叉搜索树和多边形三角剖分。在 C++ 中,可以使用动态规划高效地计算它们,这可以避免递归的低效率。了解如何实现卡特兰数可以提高解决问题的能力,尤其是在优化递归结构的算法方面。它们在离散数学和计算机科学中的多功能性,加上其指数增长,使其成为在理论和实践中处理复杂组合挑战的重要工具。 下一个主题C++ 中的翻转等价二叉树 |
在本文中,我们将讨论 C++ 和 Haskell 之间的区别。在讨论它们之间的区别之前,我们必须了解 C++ 和 Haskell。什么是 C++? C++ 是一种强大的面向对象的、高级的、静态类型的编程语言,它也是冲动的,并且是用...实现的。
阅读 4 分钟
存在一只松鼠、几颗坚果和一棵树。二维网格的单元格表示位置。最终,我们想确定松鼠为了单独收集每颗坚果并将其放到树下而可以走的最短路径。可以向...
阅读 4 分钟
素数在数论、密码学、计算机科学和工程学等各个领域都发挥着核心作用。高效地生成给定限制内的素数是一个经典问题,已经使用不同的算法来解决。其中,苏丹杜姆筛法...
阅读 13 分钟
抽样在数据科学和统计学中发挥着作用,它使我们能够从更大的总体中提取子集。一种有效的方法是水库抽样,它涉及从大小为 (n) 的数据集或流中选择固定数量的项目 (k)。本文旨在介绍... ...
阅读 6 分钟
简介:(C++23 中可用) 是 range 库的一部分,位于 <ranges> 头文件中。它允许您生成多个范围的笛卡尔积,创建一个迭代这些范围中所有可能元素组合的视图。std::views::cartesian_product 的目的 std::views::cartesian_product 提供了一个高效的...
阅读 10 分钟
在编程语言列表中,每种语言都针对特定的目标和应用而设计。C++ 和 Erlang 就是这样两种语言;它们代表了截然不同的开发方法,并且面向不同的软件构建范围。在本文中,我们将讨论...
阅读 4 分钟
在 C++ 中,Yen 的 K-最短路径算法在加权图中查找源和目的地之间的 K 条最短唯一路径。Yen 的方法通过产生先前确定的路径的偏差来迭代地寻找最短路径(由 Dijkstra 算法发现)。存储了一个优先队列...
阅读 12 分钟
本文解释了莫兰数 (Moran Numbers) 的概念,并特别提到了 C++。莫兰数是数论中的另一个实体,因为它们具有完全不同的除法性质。它提供了更多关于数字的数字之间关系的见解...
5 分钟阅读
引言 编写无 bug 的代码是开发人员的一项挑战性任务,但随着现代 C++ 的出现,这个过程变得更加容易管理。现代 C++ 指的是 C++11 及后续版本中引入的功能,带来了代码安全性、可读性和可维护性的显著改进。这...
阅读 12 分钟
Python 是一种解释型、面向对象的语言,它开箱即用地提供了动态类型、反射和高级数据类型等强大功能。其关键优势之一是 Python 丰富且功能强大的对象模型,它能够实现快速应用程序开发以及简洁、可读的代码。然而,对于 CPU 或...
5 分钟阅读
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India