import java.util.Scanner;
public class combination {
public static int k1=0; //计数k1
public static int k2=0; //计数k2
/*全排列统计个数*/
public static int count(int n){
if(n==0){
return 1;
}
return n*count(n-1);
}
/*排列统计个数*/
public static int p_count(int m,int n){
return count(m)/count(n);
}
/*组合统计个数*/
public static int c_count(int m,int n){
return count(m)/(count(n)*count(m-n));
}
/*交换*/
public static void swap(int[] list,int a,int b){
int temp;
temp=list[a];
list[a]=list[b];
list[b]=temp;
}
/*排列*/
public static void permu(int[] list,int m,int n,int u){
if(m==list.length-u+1){
k1++;
System.out.print("第"+k1+"种排列: ");
for(int i=0;i<list.length-u+1;i++)
System.out.print(list[i]);
System.out.println();
}else{
for(int i=m;i<=n;i++){ // 从后往前依次选定一个
swap(list,m,i); // 选定一个后
permu(list,m+1,n,u); // 对m+1后面继续进行递归
swap(list,m,i); //在最后两个数字之间交换位置,实现两个数字的全排列
}
}
}
/*组合*/
public static void comb(int[] list, int n, int m, int[] sub,int k) {
if (m == 0) {
k2++;
System.out.print("第"+k2+"种组合: ");
for (int i = 0; i <k; ++i) {
System.out.print(sub[i]);
}
System.out.println();
} else {
for (int i = n; i >= m; --i) { // 从后往前依次选定一个
sub[m - 1] = list[i - 1]; // 选定一个后
comb(list, i - 1, m - 1, sub,k); // 从前i-1个里面选取m-1个进行递归
}
}
}
/*主函数*/
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int[] array={0,1,2,3,4,5,6,7,8,9};
int[] sub = new int[array.length]; //存储子组合数据的数组
System.out.println("----------------------选择操作-------------------");
System.out.println("---------0 :10选4的组合 1:全排列---------");
System.out.print("请输入操作:");
int c=scan.nextInt();
if(c==1){
System.out.println("10个数字的全排列个数为:"+p_count(10,1)); //A(10,1)
permu(array,0,9,1); //A(10,1)种情况的列出
}
if(c==0){
System.out.println("10选4的组合个数为:"+c_count(10,4)); //C(10,4)
comb(array, array.length, 4, sub,4); //C(10,4)种情况的列出
}
if(c!=0&&c!=1)
System.out.println("输入有误!");
}
}
/**
* n个元素选m个元素的组合问题的实现. 原理如下:
* 从后往前选取, 选定位置i后, 再在前i-1个里面选取m-1个.
* 如: 1, 2, 3, 4, 5 中选取3个元素.
* 1) 选取5后, 再在前4个里面选取2个, 而前4个里面选取2个又是一个子问题, 递归即可;
* 2) 如果不包含5, 直接选定4, 那么再在前3个里面选取2个, 而前三个里面选取2个又是一个子问题, 递归即可;
* 3) 如果也不包含4, 直接选取3, 那么再在前2个里面选取2个, 刚好只有两个.
* 纵向看, 1与2与3刚好是一个for循环, 初值为5, 终值为m.
* 横向看, 该问题为一个前i-1个中选m-1的递归.
*/