前几天同学提到编程实现排列组合的算法, 要能把排列组合的结果输出. 想了一段时间未果, 同学的思路是使用递归, 比如求解找出 n 个数中 m 个数的排列和组合:
step a) 求解后 n-1 个数中 m 个数的排列组合; // P(n-1, m) 或 C(n-1, m)
step b) 求解后 n-1 个数中 m-1 个数的排列组合; // P(n-1, m-1) 或 C(n-1, m-1)
基本情况: m 为 0 时返回.
整个过程复杂度 O(n^2), 空间需要 P(n, m)*m 或者 C(n, m)*m.
下面是从网上找到的排列组合算法, 我觉得挺巧的, 最后面是一个利用 C++ STL 库函数实现的排列组合算法 (与前面的无关), 复杂度未知 (应该取决于库函数的内部实现吧).
1.1 组合算法
本程序的思路是开一个数组,其下标表示 1 到 m 个数,数组元素的值为 1 表示其下标代表的数被选中,为 0 则没选中。
首先初始化,将数组前 n 个元素置 1,表示第一个组合为前 n 个数。
然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。
当第一个“1”移动到数组的 m-n 的位置,即 n 个“1”全部移动到最右端时,就得到了最后一个组合。
例如求 5 中选 3 的组合:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5
1.2 全排列算法
从 1 到 N,输出全排列,共 N! 条。
分析:用 N 进制的方法吧。设一个 N 个单元的数组,对第一个单元做加一操作,满 N 进一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没有则说明得到了一个排列方案。
2 C++ STL 的排列组合方法实现: 最近一直在看 << C++ 标准程序库 >> 这本书,在看到"变序性算法"部分的时候,发现两个函数 next_permutation, prev_permutation 对于我们平时处理排列组合的问题很有帮助,根据书上的介绍写了两个个测试函数:
{
vector<int> v;
INSERT_ELEMENTS(v, 1,3);
PRINT_ELEMENTS(v, "myself: ");
while(next_permutation(v.begin(), v.end()))
{
PRINT_ELEMENTS(v, "");
}
}
void conbine()
{
vector<int> v;
INSERT_ELEMENTS(v, 1,3);
PRINT_ELEMENTS(v, "myself: ");
sort(v.begin(), v.end(), greater<int>());//增加排序(降序)
while (prev_permutation(v.begin(), v.end()))
{
PRINT_ELEMENTS( v, "");
}
}