现在的位置: 首页 > 综合 > 正文

组合算法的实现(递归法)

2019年09月13日 ⁄ 综合 ⁄ 共 3391字 ⁄ 字号 评论关闭

从n个数字选出m个数字的组合


1.递归方法一

代码如下:

public class MathCombine {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
	
		int array[]={11,22,33,44,55};
		int [][] ret=getCombine(array.length,3);
		if(null!=ret)
		{
			System.out.println("组合顺序如下:");
			for (int j = 0; j < ret.length; j++) 
			{
				for (int j2 = 0; j2 < ret[j].length; j2++) 
				{
					System.out.print("["+(j2+1)+"]="+(ret[j][j2]+1)+";");
				}
				System.out.print("\n");
			}
			
			System.out.println("\n组合结果如下:");
			for (int j = 0; j < ret.length; j++) 
			{
				System.out.print("{");
				for (int j2 = 0; j2 < ret[j].length; j2++) 
				{
					System.out.print(array[ret[j][j2]]+((j2==ret[j].length-1)?"":","));
				}
				System.out.print("}\n");
			}
			
		}
	}

	
	/**
	 * 最原始递归方法
	 * 1.从前面的m个位置移动到末尾(如:11100移动到00111)
	 * 2.其中前面m位的移动条件分别是小于(n-m)...(n-2),(n-1),n;
	 * 3.当条件2发生时(当0-m个位置,假设p),需要考虑p-1的取值,P+1以及以后的取值
	 */
	public static int[][] getCombine(int n, int m)
	{
		if(m <=0 || m>n)
		{
			return null;
		}
		else
		{
			int count=getallCombineCount(n,m);
			int [][] ret=new int[count][m];
			
			int index=0;
			int []indexArray=new int[m];
			for (int i = 0; i < indexArray.length; i++) 
			{
				indexArray[i]=i;
				ret[index][i]=i;
			}
			
			boolean isBreak=false;
			while(!isBreak)
			{
				for (int i = m-1; i >= 0; i--)
				{
					int nextValue = indexArray[i] + 1;
					if(nextValue > i+(n-m))//其中i+(n-m)表示i位置处允许的最大索引值
					{
						if(i-1>= 0)
						{
							int preValue=indexArray[i-1]+1;
							if(preValue>i+(n-m)-1)
							{
								continue;
							}
							else
							{
								indexArray[i-1]=preValue;
								for (int j = i; j < m; j++) 
								{
									if (j == m-1 )
									{
										indexArray[j]=indexArray[j-1];
									}
									else
									{
										indexArray[j]=indexArray[j-1]+1;
									}
								}	
								break;
							}
						}
						else
						{
							isBreak=true;
							break;
						}
					}
					else//满足条件
					{
						indexArray[i]=nextValue;
						index++;
						for (int j = 0; j < indexArray.length; j++) 
						{
							ret[index][j]=indexArray[j];
						}
						break;
					}
				}
				
				if(index>=count-1)
				{
					isBreak=true;
				}
			}
			return ret;
		}
	}
	
	/**
	 * 获取组合总数
	 * @param n
	 * @param m
	 * @return
	 */
	public static int getallCombineCount(int n, int m)
	{
		return getAllCount(n,m)/getFactorial(m);
	}
	
	
	/**
	 * 总数量
	 * @param m
	 * @return
	 */
	public static int getAllCount(int n,int m)
	{
		int ret=1;
		for (int i = 0; i < m; i++) 
		{
			ret*=n;
			n--;
		}
		return ret;
	}
	
	/**
	 * 阶乘
	 * @param m
	 * @return
	 */
	public static int getFactorial(int m)
	{
		return m*(m>1?getFactorial(m-1):1);
	}
}

打印结果如下:


2.递归方法二

代码如下:

public class MathCombine2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
	
		int array[]={11,22,33,44,55};
		int [][] ret=getCombine2(array.length,3);
		if(null!=ret)
		{
			System.out.println("组合顺序如下:");
			for (int j = 0; j < ret.length; j++) 
			{
				for (int j2 = 0; j2 < ret[j].length; j2++) 
				{
					System.out.print("["+(j2+1)+"]="+(ret[j][j2]+1)+";");
				}
				System.out.print("\n");
			}
			
			System.out.println("\n组合结果如下:");
			for (int j = 0; j < ret.length; j++) 
			{
				System.out.print("{");
				for (int j2 = 0; j2 < ret[j].length; j2++) 
				{
					System.out.print(array[ret[j][j2]]+((j2==ret[j].length-1)?"":","));
				}
				System.out.print("}\n");
			}
			
		}
	}

	
	/**
	 * 首先从n个数中选取编号最大的数,然后在剩下的n-1个数里面选取m-1个数,直到m-1为1为止。
	 * @param n
	 * @param m
	 * @return
	 */
	public static int[][] getCombine2(final int n , final int m)
	{
		if(m <=0 || m>n)
		{
			return null;
		}
		else
		{
			int count=getallCombineCount(n,m);
			final int [][] ret=new int[count][m];

			
			Runnable mCombineRunnable=new Runnable() {
				
				int index=0;
				int []arrayIndex=new int[m];
				
				@Override
				public void run() {
					
					index=0;
					arrayIndex=new int[m];
					getCombine2Data(n,m,arrayIndex);
				}
				
				public void getCombine2Data(int n , int m ,int[]arrayIndex)
				{
					for (int i = n; i >= m; i--) 
					{
						arrayIndex[m-1]=i-1;
						if(m>1)
						{
							getCombine2Data(i-1,m-1,arrayIndex);
						}
						else
						{
							for(int k = arrayIndex.length-1;k>=0;k--)
							{
								ret[index][arrayIndex.length-k-1]=arrayIndex[k];
							}
							index++;
						}
					}
				}
			};
			mCombineRunnable.run();
			mCombineRunnable=null;

			return ret;
		}
		
	}
	

	
	/**
	 * 获取组合总数
	 * @param n
	 * @param m
	 * @return
	 */
	public static int getallCombineCount(int n, int m)
	{
		return getAllCount(n,m)/getFactorial(m);
	}
	
	
	/**
	 * 总数量
	 * @param m
	 * @return
	 */
	public static int getAllCount(int n,int m)
	{
		int ret=1;
		for (int i = 0; i < m; i++) 
		{
			ret*=n;
			n--;
		}
		return ret;
	}
	
	/**
	 * 阶乘
	 * @param m
	 * @return
	 */
	public static int getFactorial(int m)
	{
		return m*(m>1?getFactorial(m-1):1);
	}
}

打印结果如下:

抱歉!评论已关闭.