n选m个元素组合java实现

本程序实现n选m个元素的组合,若要实现组合,可以选出每组之后用之前博文提到的全排列即可:

package edu.pku.ss.hlj;
public class Combine{

	public static String[] getPortfolio(String[] numbers,int n)
		 {
			 /*
			  * 本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标  
				  代表的数被选中,为0则没选中。    
				  首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。    
				  然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为  
				“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。    
				  当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得  
				  到了最后一个组合。    
				  例如求5中选3的组合:    
				  1  1  1  0  0  //1,2,3    
				  1  1  0  1  0  //1,2,4    
				  1  0  1  1  0  //1,3,4    
				  0  1  1  1  0  //2,3,4    
				  1  1  0  0  1  //1,2,5    
				  1  0  1  0  1  //1,3,5    
				  0  1  1  0  1  //2,3,5    
				  1  0  0  1  1  //1,4,5    
				  0  1  0  1  1  //2,4,5    
				  0  0  1  1  1  //3,4,5  
			  */
			 
			 int m=numbers.length;  //参数数组长度
			 int l=1;               //构造数组长度标志
			 for(int s=m;s>m-n;s--) //获得排列数组长度L
			 {
				 l=l*s;
			 }
			 
			 for(int z=n;z>1;z--)
			 {
				 l=l/z;
			 }                     
			
			 String[] rs = new String[l];           //返回结果
			 
			 String str="";                     //将第一种排列存入数组RS(即所有1都在左边的情况)
			 for(int x=0;x<n;x++)
			 {
				 str=str+numbers[x]+",";
			 }
			 rs[0]=str;	 
			 
			 int[] s=new int[m];    //构造下标数组
			 boolean flag=true;     //循环开关
			 int k=1;               //返回结果数组长度(自增长)
			 
			 for(int i=0;i<m;i++)   //初始化构造下标数组
			 {
				 if(i<n)
					 s[i]=1;
				 else
					 s[i]=0;
			 }
			 do{
				 flag=false;                        //初始FLAG
				 int zerocount=0;                  //10转换01前的0的个数
				 for(int i=0;i<m-1;i++)
				 {
					 if(s[i]==0)                   //记录前0个数(非0即1),可以通过这个参数进行1的前移 
					 {
						 zerocount++;
					 }
					 if(s[i]==1&&s[i+1]==0)        //10变成01 
					 {
						s[i]=0;s[i+1]=1;
						
						flag=true;                 //如果成功转换,flag设置为0,如果没有证明所以1已经移动到最后,故可以跳出DO循环
						
						for(int j=0;j<i;j++)       //10转换01前的所有1前移操作
						{
							if(j<i-zerocount)
								s[j]=1;
							else
								s[j]=0;
						}
						String returnstr="";       //用于存储变化后的构造数组
						
						for(int kk=0;kk<m;kk++)    //通过构造数组下标,得到需要的返回串
						{
							if(s[kk]==1)
							{
								returnstr=returnstr+numbers[kk]+",";
							}
						}
						
						rs[k]=returnstr;           //将串存入RS数组,用于返回   
						i=m;                       //转换了第一个10后,就要跳出该次FOR循环,所以将i直接置成m
						k++;                       //rs返回数组下标向后推一位,用于存储下个返回串
					 }
				 }
			 }while(flag==true);                    
			 
			 return rs;
		 }
	public static void main(String[] args) {
		String[] strs = new String[]{"1","2","3","4","5","6"};
		strs = getPortfolio(strs, 3);
		for(String s : strs){
			System.out.print(s+" ");
		}
	}

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值