java实现排列组合实现

        在网上下载了一个实现各种算法的文档,其中有一个实现输出数字或者说元素所有排列顺序的程序。乍一看认为很简单但,于是想自己实现一下。但是试了试,比我想象的要困难。首先说明一下我要干什么:

        比如:一组数字12,需要输出;12,21.

如果是1,2,3需要输出123
132
213
231
321
312

 

文档里提到了递归的思想, 于是就用递归的思想编一下。

用递归实现的过程实在是有些烦人,不知在何处递归,不知在何处打印。于是仔细的过了几遍程序和算法的实现过程。

第一步应该是第一个数依次和后边的换:

1234,2134,3213,4231

然后第二个和依次后边的换

1234    1234
             1324
             1432
2134    2134
             2314
             2431
3214    3214
             3124
             3412
4231    4231
             4321
             4132

然后第三个和第四个换:

1234 1234  1234
                      1243
           1324  1324
                      1342
           1432  1432
                      1423
2134  2134  2134
                       2143
            2314  2314
                       2341
            2431  2431
                       2413
3214  3214   3214
                       3241
           3124   3124
                       3142
          3412    3412
                       3421
4231 4231   4231
                       4213  
           4321   4321
                       4312
           4132   4132
                      4123


在试了很多次递归不成功后,于是写了一个用for循环实现4个元素任意排列的(方便改成递归):

public class Pailie {
 public static void main(String args[]){
	int a[]={1,2,3,4};
	for(int i=0;i<a.length;i++){
		int temp=0;
		temp=a[0];
		a[0]=a[i];
		a[i]=temp;
		                     for(int i1=1;i1<a.length;i1++){temp=a[1];
		            		a[1]=a[i1];
		            		a[i1]=temp; 
		            		for(int i2=2;i2<a.length;i2++){temp=a[2];
		            		a[2]=a[i2];
		            		a[i2]=temp;for(int p=0;p<a.length;p++){System.out.print(a[p]);}System.out.println();temp=a[2];
		            		a[2]=a[i2];
		            		a[i2]=temp;}
		            		temp=a[1];
		            		a[1]=a[i1];
		            		a[i1]=temp;}
		
		temp=a[0];
		a[0]=a[i];
		a[i]=temp;
	}}}
 


 上边的是用最里层的循环打印,打印完之后,再复原到1234的状态。其中每一层循环都是获得需要的排列之后,然后再复原。经过分析以上的代码得到了下边可以获得所有排列的递归程序: 
 

public class Pailie {
   public void pl(int x,int y[]){
	   Pailie s1=new Pailie(); 
	  for(int i=x;i<y.length;i++){
		  int temp=0;
              //这里实现按照传入的参数交换指定的两个元素
              temp=y[x];
	      y[x]=y[i];
	      y[i]=temp;  
                //这个if条件可以看作是递归的出口
                 if(x<y.length-1){
                 //通过x的递增实现x元素的右移。
                 s1.pl(x+1, y);
                //这个条件去除重复的打印(对应for循环的最内层打印)
                 if(x==y.length-2){for(int p=0;p<y.length;p++){System.out.print(y[p]);}System.out.println();}}
	        //还原
               temp=y[x];y[x]=y[i];y[i]=temp;
	    }}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a[]={1,2,3,4};		
		Pailie s=new Pailie();
      s.pl(0, a);
      	}

}
上边的程序实现了对任意个元素的全排列,是严格按照上边说明的顺序及方法实现排列。需要说明的是这条程序可能在算法和执行上有可以简化的地方,但是易于理解。

下边贴一下,我在网找到的一段代码及其说明;

//排列组合
//说明:
//将一组数字、字母或符号进行排列,以得到不同的组合顺序,例如1 2 3这三个数的排列组合有:1 2 3、1 3 2、2 1 3、2 3 1、3 1 2、3 2 1。
//解法:
//可以使用递回将问题切割为较小的单元进行排列组合,例如1 2 3 4的排列可以分为1 [2 3 4]、2 [1 3 4]、3 [1 2 4]、4 [1 2 3]进行排列,这边利用旋转法,先将旋转间隔设为0,将最右边的数字旋转至最左边,并逐步增加旋转的间隔,例如:
//1 2 3 4 -> 旋转1 -> 继续将右边2 3 4进行递回处理
//2 1 3 4 -> 旋转1 2 变为 2 1-> 继续将右边1 3 4进行递回处理
//3 1 2 4 -> 旋转1 2 3变为 3 1 2 -> 继续将右边1 2 4进行递回处理
//4 1 2 3 -> 旋转1 2 3 4变为4 1 2 3 -> 继续将右边1 2 3进行递回处理 
//
//实现:
//java实现
public class Permutation {
	public static void perm(int[] num, int i) {
		if(i < num.length - 1) {
			for(int j = i; j <= num.length - 1; j++) {
				int tmp = num[j];
				// 旋转该区段最右边数字至最左边
				for(int k = j; k > i; k--)
					num[k] = num[k-1];
				num[i] = tmp;
				perm(num, i+1);
				// 还原
				for(int k = i; k < j; k++)
					num[k] = num[k+1];
				num[j] = tmp;
			}
		}
		else {
			// 显示此次排列
			for(int j = 1; j <= num.length - 1; j++)
			System.out.print(num[j] + " ");
			System.out.println();
		}
	}
    public static void main(String[] args) {
		int[] num = new int[4+1];
		for(int i = 1; i <= num.length - 1; i++)
		   num[i] = i;
		perm(num, 1);
    }
}
在网上搜了一下还有非递归的方法,当然是采用新的算法。搜一下全排列非递归实现就行了。上边粘来的代码是按照字典顺序输出的,相关信息请搜索。我的那段原创代码,可能有冗余的地方,但是我贴出了思考的过程易于理解。另外希望看到评论

猜你喜欢

转载自blog.csdn.net/jnitjy/article/details/39804863