当前位置: 首页 > news >正文

数据结构:递归:组合数(Combination formula)

目录

推导组合数的递归公式

杨辉三角 = 组合数图谱

🌳递归调用树可视化

代码实现


我们来分析“递归中的 Combination formula 问题”,也就是常说的组合数计算问题

推导组合数的递归公式

什么是组合问题?

组合问题的本质是从 n 个元素中选择 k 个元素,不考虑顺序,有多少种选法。

Step 1: 从一个最简单的事实出发

我们从两个最基本的事实(第一性)出发:

从 0 个数中选 0 个,有 1 种选法:C(0,0)= 1

从 n 个数中选 0 个,或者选 n 个,只有 1 种方式:C(n,0) = C(n,n) = 1

这是我们的边界条件(Base Cases)。 

Step 2:构建思维模型:是否包含第 n 个元素?

我们从一个关键思想出发:
从 n 个元素中选 k 个,可以分为两类情况:

  • 不选第 n 个元素:从前 n-1 个元素中选 k 个,记作 C(n-1, k)

  • 选第 n 个元素:剩下从前 n-1 个元素中选 k-1 个,记作 C(n-1, k-1)

所以,我们得到核心递归关系:

这就是组合数的递归本质 —— 不依赖任何公式推导的、基于逻辑分类讨论的解法。 

Step 3: 示例验证:

比如:从 4 个元素中选 2 个:

C(4, 2) = C(3, 2) + C(3, 1)

  • C(3, 2) =从前3个中选2个(不选第4个)

  • C(3,1)= 从前3个中选1个(因为已经选了第4个)

最终两者加起来就是从4个中选2个的方法总数。

🔍这就是递归(recursion)

  • 大问题 C(n,k)

  • 分解为两个更小的问题 C(n−1,k) 和 C(n−1,k−1)

  • 一直递归下去,最终会到达 base case:C(n,0) 或 C(n,n)


杨辉三角 = 组合数图谱

杨辉三角其实就是组合数的排列。三角形第 n 行的第 k 个数,就是: C(n,k)

Row n →          k →11     11     2     11     3     3     11     4     6     4     1
---------------------------------杨辉三角(Pascal's Triangle)

对应数值(左对齐)如下: 

n\k →  0   1   2   3   4
0     1
1     1   1
2     1   2   1
3     1   3   3   1
4     1   4   6   4   1

举例:

即:杨辉三角中每个数都是其左上和右上两个数之和。 

🌳递归调用树可视化

我们现在来画出计算C(4,2)的递归调用树,它完美对应杨辉三角的构建过程:

               C(4,2)/      \C(3,2)     C(3,1)/    \      /    \C(2,2) C(2,1) C(2,1) C(2,0)|       |     |      |1       ?     ?      1/ \   / \C(1,1) C(1,0) C(1,0) C(1,1)|     |     |     |1     1     1     1

所有底层节点(如 C(2,0), C(2,2), C(1,0), C(1,1))为 base case(边界条件)。

通过不断向下分解为两个更小的问题,每个组合数都是上层两个的和。

组合公式与递归的几何意义

  1. 杨辉三角的每一行的数值,都是通过上面两数之和得到;

  2. 这就意味着,从 n−1 行中,取 k−1 和 k 的值,就能得到 n 行的第 k 个值。

你可以这样理解:

  • C(n, k) 就像在杨辉三角中往下走到第 n 行第 k 个位置;

  • 这个点的值由它“上方的两个点”(即 C(n−1,k−1) 和 C(n−1,k))决定;

所以,组合公式其实是动态构建杨辉三角的路径图。

 ​​​​​​代码实现

 处理边界条件(base case)

    if (k == 0 || k == n)return 1;

思路说明:

  • 从 n 个中选 0 个只有 1 种方式:什么都不选;

  • 从 n 个中选全部(即 k = n)也只有 1 种方式;

这就是我们的递归终止条件,防止无限递归。

✅ 写递归公式

    return combination(n - 1, k - 1) + combination(n - 1, k);

组合的核心递推思想是:

  • 选 or 不选当前元素:

    • 不选:从前 n−1 个中选 k 个;

    • 选了当前:从前 n−1 个中选 k−1个。

这正是递归的两个分支。

✅ 完整函数如下 

int combination(int n, int k) {if (k == 0 || k == n)return 1;return combination(n - 1, k - 1) + combination(n - 1, k);
}

完整代码

#include <iostream>
using namespace std;int combination(int n, int k) {if (k == 0 || k == n)return 1;return combination(n - 1, k - 1) + combination(n - 1, k);
}int main() {cout << combination(5, 2) << endl;  // 输出 10return 0;
}
http://www.lryc.cn/news/578695.html

相关文章:

  • sqlmap学习ing(2.[第一章 web入门]SQL注入-2(报错,时间,布尔))
  • 【C++】inline的作用
  • 《UE5_C++多人TPS完整教程》学习笔记40 ——《P41 装备(武器)姿势(Equipped Pose)》
  • SQL学习笔记6
  • Linux基本命令篇 —— grep命令
  • python训练day46 通道注意力
  • 【Python】断言(assert)
  • 【1.7 漫画Java核心并发编程】
  • 【Unity实战】UI按钮回调管理:职责分离与持久化策略
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的抖音渠道力拓展与多渠道利润增长研究
  • react-别名路径配置
  • Git 运行.sh文件
  • Hadoop、Spark、Flink 三大大数据处理框架的能力与应用场景
  • SSVEP Next:现代化的 SSVEP 可视化 Web 快速实现
  • GPT-1论文阅读:Improving Language Understanding by Generative Pre-Training
  • OSPF虚拟链路术语一览:快速掌握网络路由
  • rocketmq 之 阿里云转本地部署实践总结
  • Rust 是什么
  • GPIO详解:不仅仅是输入输出那么简单
  • RagFlow 源码部署启动指南
  • 【文件读取】open | with | as
  • js filter()
  • 从docker-compose快速入门Docker
  • Linux安装JDK和Maven
  • Day 3:Python模块化、异常处理与包管理实战案例
  • 基于GD32 MCU的IAP差分升级方案
  • Vue基础(19)_Vue内置指令
  • STM32——代码开发顺序
  • 模型部署与推理--利用python版本onnxruntime模型部署与推理
  • (25.07)解决——ubuntu20.04系统开机黑屏,左上角光标闪烁