组合算法-C++实现

来源:互联网 发布:onlyanna淘宝 编辑:程序博客网 时间:2024/06/05 10:23

<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);">方法一、递归,简单但低效</span>

思想:在n个元素中选取k个元素组成一个组合,那么至少有一个元素位于序号[k~n]。

那么,combine(n, k) = ([n]+Combine(n-1, k-1)) + ([n-1] + Combine(n-2, k-1)) + ... + ([k] + Combine(k-1, k-1));

因为[n]+Combine(n-1, k-1)确定了所有包含[n]组合的情况,([n-1] + Combine(n-2, k-1))确定了所有包含[n-1]却不包含[n]的组合,其它的依次类推。

//1~n中选取k个数的所有组合void Combine(int n, int k, int initK){    for (int i=n; i>=k; i--)    {        seq[k] = i;        if (k>1)        {            Combine(i-1, k-1, initK);        }        else        {            count++;            for (int j=1; j<=initK; ++j)            {                cout<<seq[j]<<" ";            }            cout<<endl;        }    }}

方法二、使用二进制方法,复杂些但高效很多

我们还是以1,2,3,4,5中选2个数为例。

我们这次的排列非常的像,我们用一个五个数的数组表示一个5位数的二进制数字,(其中1表示选中该数字,0则不是)这样用一个二进制数来表示一个排列。如果这个二进制遍历所有的可能性(0~31),且只有两个1组成的话,就是一个我们想要的排列结果。这里我们换成十进制从左往右换算,发现刚好是从小到大。

1,2 (1,1,0,0,0) -- 3(十进制)

1,3 (1,0,1,0,0) -- 5

2,3 (0,1,1,0,0) -- 6

1,4 (1,0,0,1,0) -- 9

2,4 (0,1,0,1,0) -- 10

3,4 (0,0,1,1,0) -- 12

1,5 (1,0,0,0,1) -- 17

2,5 (0,1,0,0,1) -- 18

3,5 (0,0,1,0,1) -- 20

4,5 (0,0,0,1,1) -- 24


如何用代码实现呢?

需要用以下策略:

1.m 选 n, 初始化m个数,它们都是0,前n个都变成1,表示最小的二进制。

2.如何找到下一个较大的数呢?因为我们这里的二进制是从左往右,所以,当发现一个1,0时,我们把它改成0,1的时候,这个数就变大了!

3.根据策略2的话(0,1,1,0,0)--6下一个二进制数应该是(0,1,0,1,0)--10,但是比(0,1,1,0,0)要大的下一个数应该是(1,0,0,1,0)--9。所以

我们要把1,0换成0,1的时候,还要把0,1中0的前面所有1都移到最前面,这样才是最小的数,大家理解下这句。因为我们的二进制是从左往右的。

代码如下,非常简短。

<span style="font-size:10px;">// MyCombination.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <iostream>#include <vector>#include <algorithm>using namespace std;void printResult(vector<int>& vecInt, int t[]){for(int i = 0; i < vecInt.size(); ++i){if(vecInt[i] == 1){cout << t[i] << " ";}}cout << endl;}bool compare(int a, int b){if(a > b){return true;}else{return false;}}void combination(int t[], int c, int total){//initial first combination like:1,1,0,0,0vector<int> vecInt(total,0);for(int i = 0; i < c; ++i){vecInt[i] = 1;}printResult(vecInt, t);for(int i = 0; i < total - 1; ++i){if(vecInt[i] == 1 && vecInt[i+1] == 0){//1. first exchange 1 and 0 to 0 1swap(vecInt[i], vecInt[i+1]);//2.move all 1 before vecInt[i] to leftsort(vecInt.begin(),vecInt.begin() + i, compare);//after step 1 and 2, a new combination is existprintResult(vecInt, t);//try do step 1 and 2 from fronti = -1;}}}int _tmain(int argc, _TCHAR* argv[]){const int N = 5; int t[N] = {1, 2, 3, 4, 5};combination(t, 2, N);system("pause");return 0;}</span><span style="font-size: 18px;"></span>





0 0
原创粉丝点击