编写算法输出从n个数中取k个(k小于等于n)的所有组合

编写算法输出从n个数中取k个(k小于等于n)的所有组合,要求每个组合是从大到小的顺序

例如,当n=5,k=3时,你的算法该输出:543,542,541,532,531,521,432,431,421,321 

这是一道东大的自主考研的题目,咋一看貌似不难,没想到做起来就尴尬了,简单的利用循环是不行的,必须要采用其他的方法。一下是这道题的一些解法,以后要找到了好的方法陆续加进去,欢迎大家把自己的方法贴出来O(∩_∩)O~

1递归的方法,这种方法是从网上搜到,不知道是谁写的了(先偷一下),我把它改成了c++的代码,并简单的加了注释。

#include "stdafx.h"
#include <iostream>
using namespace std;

void f(int n,int k,int a[],int m)
{
    int i;				

	//当k==0的时候,将数组里面的三个数依次输出
    if( k == 0 )
    {		
        for(int j= 0; j < m; ++j)
            cout<<a[j];
        cout<<" ";
    }

    else
    {
        for( i = n; i >= k; --i )
        {
            a[m] = i;
            f(i-1,k-1,a,m+1);
        }  //for
    }  //else
}

void main()
{
    int n,k,m=0;
    int a[10];  //临时存放结果的数组
    cout<<"Please enter n and k :";
    cin>>n>>k;
    f(n,k,a,m);
    cout<<endl;
}

2.01交换法

本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标 
代表的数被选中,为0则没选中。 
首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。 
然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为 
“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。 
当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得 
到了最后一个组合。 
例如求5中选3的组合: 
1 1 1 0 0 //5,4,3 
1 1 0 1 0 //5,4,2
1 0 1 1 0 //5,3,2
0 1 1 1 0 //4,3,2
1 1 0 0 1 //5,4,1

~~~~~省略

#include "stdafx.h"
#include <iostream>
using namespace std;

//输出数组中的内容
void print(int arr[],int size)
{
	for( int i =0; i<size; i++)
	{
		if ( arr[i] == 1 )
			cout<<size-i<<" ";   
	}
	cout<<endl;
}

/*******************************************************************
文字部分说的左移的操作,这里不采用真正的左移,而是采用以下方法:
1.统计1的个数count,
2.将这部分数组清零
3.从数组开始的部分赋值count个1
*********************************************************************/
void leftShit(int arr[], int size)
{
	int count =0;    //统计1的个数

	for ( int j = size; j >= 0; --j)
	{
		if ( arr[j] == 1)  ++count;
	}

	if (count == 0)  return;

	for ( int j = size; j >= 0; --j)
	{
		arr[j] = 0;
	}


	for ( int j=0; j<count;++j)
	{
		arr[j]=1;
	}

}

void exchangeOrder(int arr[], int size)
{
	 print(arr,size);
	bool flag = true;   //当扫描一遍没有符合条件的,终止
	while (flag)
	{
		flag = false;
	     for ( int i = 0; i < size-1; ++i)
		 {
			 if ( arr[i]== 1 && arr[i+1] == 0 ){
				 flag = true;
				 arr[i] = 0;
				 arr[i+1] = 1;

				 leftShit(arr,i);   //数组从0到i的1要左移
				 print(arr,size);
				 
				  break;
				 }

		 }
	}
}

int main()
{
	int arr[5]={1,1,1,0,0};
	exchangeOrder(arr,5);
	return 0;

}


参考文献:http://xiaomage.blog.51cto.com/293990/74094


你可能感兴趣的:(编写算法输出从n个数中取k个(k小于等于n)的所有组合)