编写算法输出从n个数中取k个(k小于等于n)的所有组合
2012-12-06 14:56
681 查看
编写算法输出从n个数中取k个(k小于等于n)的所有组合,要求每个组合是从大到小的顺序
例如,当n=5,k=3时,你的算法该输出:543,542,541,532,531,521,432,431,421,321
这是一道东大的自主考研的题目,咋一看貌似不难,没想到做起来就尴尬了,简单的利用循环是不行的,必须要采用其他的方法。一下是这道题的一些解法,以后要找到了好的方法陆续加进去,欢迎大家把自己的方法贴出来O(∩_∩)O~
代表的数被选中,为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
~~~~~省略
参考文献:http://xiaomage.blog.51cto.com/293990/74094
例如,当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个布尔量的所有可能的组合
- 输入两个整数n和m, 从数列1,2,...,n中任意选择几个数,使其和等于m, 要求编写程序输出所有的组合
- 输入两个整数n和m, 从数列1,2,...,n中任意选择几个数,使其和等于m, 要求编写程序输出所有的组合
- 编写一个算法输出n个布尔量的所有可能的组合
- 输出所有小于等于n的素数(要求1)每行输出10个(要求2)较优的算法
- 输入两个整数n和m, 从数列1,2,...,n中任意选择几个数,使其和等于m, 要求编写程序输出所有的组合
- 19. 中兴面试题:输入两个整数n和m, 从数列1,2,...,n中任意选择几个数,使其和等于m, 要求编写程序输出所有的组合
- 编写函数int fun(int lim,int aa[100]),该函数的功能是求出小于或等于lim 的所有素数并放在aa数组中,该函数返回所求的素数的个数?
- 给定一个字符串S,求所有长度小于等于3的子串出现的次数,输出结果按出现次数从大到小
- 有一个整数数组,然后有一个数m,要找到整数数组中,所有和等于m的组合,并输出。
- 给定一个正整数,编写程序计算有多少对质数的和等于输入的这个正整数,并输出结果。输入值小于1000。
- 用JAVA编写一个算法实现对一个字符数组的所有元素的所有组合
- 链表分割 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 给定一个链表的头指针 ListNode* pHead,请返回重新排列后的链表的头指针。注意:分割以
- 算法性能比较(一)——找出小于等于n的所有素数
- [素数]:编写函数,求出小于或等于lim的所有素数,并放在aa数组中,函数返回所求的素数个数。
- [面试题]设计一个算法找到数组中两个元素相加等于指定数的所有组合
- 输出1到N之间所有相加等于M的数字组合(背包问题)求相加为M的所有组合--微软酷派经典面试题
- 设顺序表 S 中元素递增有序,编写算法删除 S 所有大于 k1 且小于 k2 的元素
- 创建独立线程来输出小于或等于用户输入数的所有素数
- 程序员面试题精选(44):整数分割(即求一个数N由小于等于N的数相加所得的所有组合)