排列组合算法
排列组合的数学基础
排列
从 \(n\) 个不同元素中, 每次取出 \(m(1≤m≤n)\) 个不同元素,排成一列,称为从 \(n\) 个元素中取出 \(m\) 个元素的无重复排列或直线排列,简称排列
, 记作 \(P_n^m = \frac{n!}{(n-m)!}\);
组合
从 \(n\) 个不同元素中每次取出 \(m(0≤m≤n)\) 个不同元素,不管其顺序合成一组,称为从 \(n\) 个元素中不重复地选取 \(m\) 个元素的一个组合, 简称组合
, 记作 \(C_n^m = \frac{n!}{m! \cdot (n-m)!}\)。
全排列的递归算法描述
设一组元素 \(\Omega = \{A,B,C, \dotsb, N\}\);
当 \(n = 1\) 时: $Permutate(\Omega) = {A} $;
当 \(n = 2\) 时: \(Permutate(\Omega) = \{A, B\}, \{B, A\}\);
当 \(n = 3\) 时: \(Permutate(\Omega) = \{A, B, C\}, \{A, C, B\}, \{B, A, C\}, \{B, C, A\}, \{C, A, B\}, \{C, B, A\} \\ =A \{Permutate(\Omega - A)\} + B \{Permutate(\Omega - B)\} + C\{Permutate(\Omega - C)\}\);
...
对于 \(n\): 有 \(Permutate(\Omega) = \omega_1 \{Permutate(\Omega - \omega_1)\} +\omega_2 \{Permutate(\Omega - \omega_2)\} + \dotsb + \omega_n \{Permutate(\Omega - \omega_n)\}\)
template<class T>
void Recursion_Arrangament(int begin, int end, std::vector<T> dataSet)
{
if (begin == end) // 终止条件
{
for (size_t i = 0; i < end; i++)
{
std::cout << dataSet[i];
}
std::cout << std::endl;
}
for (size_t i = begin; i < end; i++)
{
swap(dataSet[begin], dataSet[i]);
Recursion_Arrangament(begin + 1, end, dataSet);
swap(dataSet[i], dataSet[begin]);
}
}
组合的递归算法描述
用 "10" 转换解决组合问题
在一组元素 \(\Omega = \{A,B,C, \dotsb, N\}\) 中选取 \(m\) 个作任意组合, \(Combine(N, m)\)
设 \(m = 3, n = 5\)
- 将元素数组的前三位标记为
1
, 其余标记为0
; - 从头读取标记为, 当遇到的第一组
10
时, 输出结果, 并转换10
为01
; - 重复
步骤2
, 直到队尾再没10
, 终止;
A | B | C | D | E | Output |
---|---|---|---|---|---|
1 | 1 | 1 | 0 | 0 | ABC |
1 | 1 | 0 | 1 | 0 | ABD |
1 | 0 | 1 | 1 | 0 | ACD |
0 | 1 | 1 | 1 | 0 | BCD |
0 | 1 | 1 | 0 | 1 | BCE |
0 | 1 | 0 | 1 | 1 | BDE |
0 | 0 | 1 | 1 | 1 | CDE |