排列组合问题
以组合为基础,将每个组合全排列,实现排列选择问题
实现全排列:
public static void QPaiLie(char c[],int start,int end){//用作将各个组合排列的全排列
//start从0开始,end为数组的大小(不能为最后一个的下标)
if(start==end){
//表示已经到达递归底部
for(int i=0;i<end;i++){
System.out.print(c[i]+" ");
}
System.out.println();
return;
}else{
for(int i=start;i<end;i++){
//i作为头
char temp=c[i];
c[i]=c[start];
c[start]=temp;//交换枚举
QPaiLie(c, start+1, end);//下一层递归
temp=c[i];
c[i]=c[start];
c[start]=temp;//回溯
}
}
}
将组合进行全排列处理:
public static void Show(int n,char c[],int c1[],int m){//输出选中的组合
// for(int i=0;i<n;i++){
// if(c1[i]==1){
// System.out.print(c[i]+" ");
// }
// }
// System.out.println();
char c2[]=new char[m];
int count=0;
for(int i=0;i<n;i++){
if(c1[i]==1){
c2[count++]=c[i]; //将选出来的组合赋值给一个数组,为全排列做准备
}
}
//已经有组合出来了,开始进行全排列
QPaiLie(c2, 0, m);
}
判断组合是否生效:
这里用标记每个位置1或0的方式来记录有没有被选出来过
public static boolean Judge(int n,int m,int c1[]){//判断1是否全都移到了右边
for(int i=n-1;i>=n-m;i--){
if(c1[i]==0){//只要最右面n-m还有0,就继续
return false;
}
}
return true;
}
组合实现:
public static void ZuHe(char c[],int c1[],int n,int m){//将前m个初始化为1(代表选中),其余为0(代表没有选)
//把所有的10变成01,到最后没有10为止,则全部选择过
for(int i=0;i<m;i++){
c1[i]=1;
}
Show(n,c,c1,m);//第一个组合
while(!Judge(n, m, c1)){//只要1没有全移动到最右边,就继续
for(int i=0;i<n-1;i++){
if(c1[i]==1&&c1[i+1]==0){//找10
c1[i]=0;
c1[i+1]=1;
int count=0;//指向左边1序列的最后一个
for(int j=0;j<i;j++){ //将01组合左边的1全部放在数组最左边
if(c1[j]==1){
c1[j]=0;
c1[count++]=1;
}
}
Show(n, c, c1,m);
break;//重新扫描
}
}
}
}
主代码:
public static void PaiLie(){
System.out.println("请输入一个字符串:");
Scanner scan=new Scanner(System.in);
String str=scan.nextLine();
char c[]=str.toCharArray();
int c1[]=new int[c.length];
for(int i=0;i<c.length;i++){
c1[i]=0;
}
int len=str.length();
System.out.println("请输入一个整数:");
int num=scan.nextInt();
ZuHe(c, c1, len, num);
}
样例输入:
结果: