递归:递归法解决排列问题

方法1:

程序大致结构:

约定:pl[len] //pl 为最终放置结果的数组;len为数组的长度

         ele为参与排列的个元素出现的个数

         i为pl中下标

假设参与排列的元素有ABCD

run(ele,int i){

    { 

     递归收敛判断;

     收敛后进行处理;

     }

      //递归块1

   {   若元素A的个数不为0;

          将元素A的个数减1;

          run (ele,i+1);

         将元素A的个数 加1;

     }

    

    //递归块2

   {   若元素B的个数不为0;

          将元素B的个数减1;

          run (ele,i+1);

         将元素B的个数 加1;

     }

    

 //递归块3

   {   若元素C的个数不为0;

          将元素C的个数减1;

          run (ele,i+1);

         将元素C的个数 加1;

     }

  ......

  / /递归块n

   {   若元素M的个数不为0;

          将元素M的个数减1;

          run (ele,i+1);

         将元素M的个数 加1;

     }

}

注意:在递归块内,不应对所传入的参数进行改变;每个递归块所得到的原始参数应保持一致。

举例:ABCDEF进行排列

        static int[] ele={1,1,1,1,1,1};//每个元素出现的个数
	static int len=6;排列的长度
	static char[] rst=new char[6];
	static  void run(int[] ele,int i){
		if(i==len){
			
			for(char c:rst)
				  System.out.print(c);
				System.out.print('\n');
			
		}
		
		if(ele[0]!=0){
			ele[0]--;// <span style="color:#ff0000;">对传入的参数改变了,所以必须在本块内进行恢复</span>
			rst[i]='A';
			run(ele,i+1);//<span style="color:#ff0000;">i本身没有改变
</span>			ele[0]++;//<span style="color:#ff0000;">对参数进行恢复</span>。
		}
		if(ele[1]!=0){
			ele[1]--;
			rst[i]='B';
			run(ele,i+1);
			ele[1]++;
		}
		if(ele[2]!=0){
			ele[2]--;
			rst[i]='C';
			run(ele,i+1);
			ele[2]++;
		}
		if(ele[3]!=0){
			ele[3]--;
			rst[i]='D';
			run(ele,i+1);
			ele[3]++;

		}
		if(ele[4]!=0){
			ele[4]--;
			rst[i]='E';
			run(ele,i+1);
			ele[4]++;

		}
		if(ele[5]!=0){			
			ele[5]--;// 对传入的参数改变了,所以必须在本块内进行恢复
			rst[i]='F';
			run(ele,i+1);
			ele[5]++;//对参数进行恢复。

		}	
	}

方法2:( 优化方法1)

程序结构:

 set 中存放全部复合类型ele

ele{

 Type x;//参与排列的数据类型

 int num ;//该元素可以出现的个数

len:存放排列的数组长度

参数说明:n为 集合set剩余n个元素中选择,实际没有参与运算,仅仅是为了增加程序的可读性。

                   i为存放排列的数组的下标

run(set,int n,int i){

          if(i==len){

               递归结束

             } else{


                for (Ele ele:set){

                        if(ele可用){

                               ele.num--;

                               run(set,n-1,i+1);

                              ele.num++;

           }

           }

 }

}

实例:

1234 中任取3个元素全排列

public class Main {
	
	static ArrayList<Ele> set =new ArrayList<Ele>();// 存放参与排列的元素的包装类型
	static int[] rst=new int[3];	//存放排列
      
       //  <pre name="code" class="java">       //参与排列的元素的包装类
public static class Ele{ int num;// 参与排列的元素
boolean slc;//用于控制该元素的个数,由于本例中个元素最多出现一次,故使用bool来控制 public Ele(int i, boolean b) { num=i; slc=b;// TODO Auto-generated constructor stub} }

 

        //核心程序
	static void selct(ArrayList<Ele> set,int n,int i){
		if(n==0){//<span style="color:#ff0000;">此处完全可以换成i==len来判断</span>
					
			for(int num:rst){
						
			
			System.out.print(num);
					}
					System.out.println("");
		}else{	
			
			for(Ele ele:set){
				if(!ele.slc){
				  ele.slc=true;
				  rst[i]=ele.num;
                          <span style="font-family: Arial, Helvetica, sans-serif;">//从set中其他n-1个元素进行全排列,从排列的i+1号位置开始</span>
				  selct(set,n-1,i+1);	
				  ele.slc=false;
				}				
			}
			
			
			
		}

   }
	
	
	
	public static void main(String[] args){
		
          //为参与排列的元素赋值,这里共有4个元素1234
	    for(int i=1;i<5;i++)	{	    	
	    	set.add(new Ele(i,false));   	
	    }
	    
	<pre name="code" class="java">               //从set中取3个元素进行全排列,从排列的0号位置开始
<span style="font-family: Arial, Helvetica, sans-serif;">	                     selct(set,3,0);</span>
}}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值