C++:排列组合算法

来源:互联网 发布:快速排序算法c 编辑:程序博客网 时间:2024/05/09 21:59

转载请注明出处

排列组合数是一种非常实用的工具,计算出所有的排列组合可以解决一些实际的工程问题。所以,掌握计算排列组合的方法是十分必要的。

目前,网上已经有一些计算排列组合数的算法,比如http://www.cnblogs.com/shuaiwhu/archive/2012/04/27/2473788.html 。

大部分排列组合算法都是用了递归的思想,在这里我也给出我的一个实现方法,这个算法同样采用了递归的方式,但是采用了分治的思想。

为叙述方便,我们先将问题转化成对数组的下标进行排列组合。

比如对于数组a={'a','b','c','d','e'}.

我们只需要对数组a的下标进行排列组合,之后通过下标访问即可,比如得到结果之一为(1,3,4),那么通过访问数组a即可得到最终结果(‘b’,‘d’,‘e’)。

思路:

对于求排列组合C(5,3),我们可以对结果分成两类:A类是含有下标5的结果,B类是不含下标5的结果;

同理,对于B类,我们可以将B类继续分成两类:B1类是含有下标4的结果(且不含下标5的结果),B2类是不含下标4的结果(且不含下标5的结果);

同理,对于B2类,我们可以继续分成两个子类:B21类是含有下标3的结果(且不含下标5、4的结果),B22类是不含下标3的结果(且不含下标5、4的结果);

注意,此时B22类是不成立的(应为不含下标3、4、5,只剩下下标1、2两个元素),所以已经将所有独立的子集找到,完成遍历。

其中,

对于A类,我们只需要求解C(4,2),之后再在返回的结果中加入5即可;

对于B类,可以分成B1和B2两类:

对于B1类,我们只需要求解C(3,2),之后再在返回的结果中加入4即可;

对于B2类,可以分成B21和 B22两类:

对于B21类,我们只需要求解C(2,2),之后再在返回的结果中加入3即可;

对于B22类,不成立,结束。

可以发现,问题C(5,3)已经降维成三个小问题:C(4,2),C(3,2) 和C(2,2)。利用递归的方法即可实现最终结果的求解。


下面是源代码:

/*****************************************************************************************************************************        时间复杂度:        空间复杂度:        功能:求排列组合Cij        输入参数:                int i                :        总数                int j                :          组合数                vector<int>r:        用于存储临时结果的向量,大小必须等于num                 int num                :        组合数                vector<vector<int> > & result        :        用于存储最终所有结果的二维向量         返回参数:                void        注意:                 首先建立两个向量作为函数的输入参数                                vector<int> r(num);                                //num为组合数                 vector<vector<int> > result;        //存储最终结果         使用样例:                vector<int> resulttemp(3);                vector<vector<int> > result;                Cij(6,3,resulttemp,3,result); *****************************************************************************************************************************/void Cij(int i, int j,vector<int> &r,int num,vector<vector<int> > & result){        //排列组合公式Cij        //cout << n << ' ' << i << ' ' << j << endl;        if (j == 1)        {                for (int k = 0; k < i; k++)                {                        vector<int> temp(num);                        r[num - 1] = k;                        for (int i = 0; i < num;i++)                        {                                temp[i]=r[i];                                //cout << r[i] << ' ';                        }                        result.push_back(temp);                        //cout << endl;                }        }        else if (j == 0)        {                //do nothing!        }        else        {                for (int k = i; k >= j; k--)                {                        r[j-2] = k-1;                        Cij(k - 1, j - 1,r,num,result);                }        }}

下面是测试结果:



0 0
原创粉丝点击