前几天同学提到编程实现排列组合的算法, 要能把排列组合的结果输出. 想了一段时间未果, 同学的思路是使用递归, 比如求解找出 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 对于我们平时处理排列组合的问题很有帮助,根据书上的介绍写了两个个测试函数:

void permutate()
{
    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, ""
);
    }
}