排列组合那些事

          排列问题   
 类型一:固定序列,1,2,3,...,n全排列
/*
 * 
 *   从1...n之中进行全排列,传入n,默认数据:[1,2,...,n]
 *   
 * */
public class allArrange {
    //数组的个数
	private int n;
	//数组中每个数是否被访问过的标记
	private int []x;
	//结果数组
	private int []result;
	//记录全排列种数。
	private int sum;
	
	public allArrange(int n){
		 this.n=n;
	     sum=0;
    	 x=new int [n];
    	 result=new int [n];
    	 
    	 for(int i=0;i<n;i++)
    		 x[i]=0;
    	 
           backtrack(0);	
    	 System.out.println("总共有 "+sum+" 种全排列方式");
      }
	
	private void backtrack(int t){
		//递归出口:到第n层,打印结果。
		 if(t>n-1) { print();return;}
		 
		 else{
			 //采用循环递归的方式  (回溯法)
			 for(int i=0;i<n;i++){
				 //没有被访问过,标记,记录该数,进入下一层
				if(bound(i)){
			    	 x[i]=1;
			    	 result[t]=i+1;
					 backtrack(t+1);
				     x[i]=0;
				 }
			 }
		}
	}
	
	//被访问过,则返回false
	private boolean bound(int t){
		 if(x[t]==1)return false;
		 return true;
	} 
	//打印输出
    public void print(){
		sum++;
		for(int i=0;i<n;i++)
			System.out.print(result[i]+" ");
		System.out.print("\n");
		
	}
	
}

类型二: 含重复数的全排列

public class generalAllArrange {
	private int n;
	private int []x;
	private int []result;
	private int sum;
	
    public generalAllArrange(int []a){
    	this.n=a.length;
    	x=a;
    	result=new int[n];
    	
    	/*显示更直观一点,利用快排排个序*/
    	 //sort(0,n-1);
    	 backtrack(0);
        System.out.println("总共有 "+sum+" 种全排列方式");
    }
    
	void swap(int [] arr,int m,int n){
        int temp=arr[m];
        arr[m]=arr[n];
        arr[n]=temp;
   }
	
	/*
	 * 快排函数
	 * */
	private void sort(int l,int r) {
		// TODO Auto-generated method stub
		if(l<r){
			int q=position(l,r);
			sort(l,q-1);
			sort(q+1,r);
			
		}
	}
	
	private int position(int l,int r){
		int i=l,j=r+1;
		int a=x[l];
		 
		while(true){
			 while(x[++i]<a&&i<r);
			 while(x[--j]>a);
			 if(i>=j)break;
			 swap(x,i,j);
			
		 }
		 x[l]=x[j];
		 x[j]=a;
		return j;
		
	}
	
	/*
	 * 回溯
	 * */
	private void backtrack(int t){
		 if(t>n-1) { print();return;}
		  else{
			 for(int i=t;i<n;i++){
				
				 if(bound(i)){
			    	 swap(x,i,t);
					 backtrack(t+1);
					 swap(x,i,t);
				 }
			 }
		}
	}
	
	//当后面的数和该层的数相同,则不需要交换
	private boolean bound(int t){
		
		for(int i=t+1;i<n;i++)
			 if(x[t]==x[i])return false;
		
		 return true;
	} 
	
   public void print(){
		sum++;
		for(int i=0;i<n;i++)
			System.out.print(x[i]+" ");
		System.out.print("\n");
		
	}
	
}

组合问题

类型一:

固定序列,1,2,3,...,n的K组合

/*
 * 已知非负整数n,k,列出集合S属于{1,2,...,n}的所有k组合
 * */
public class kArrange {
	   //数组个数
		private int n;
       //选取个数		
	 	private int k;
	 	//数组中每个数是否被访问过的标记
		private int []x;
		//结果数组
		private int []result;
		//记录K组合种数。
		private int sum;
		
		public kArrange(int n,int k){
			 this.n=n;
			 this.k=k;
		     sum=0;
		   
	    	 x=new int [n];
	    	 result=new int [k];
	    	 
	    	 for(int i=0;i<n;i++)
	    		 x[i]=0;
	    	 
	    	 backtrack(0);
	    	 System.out.println("总共有 "+sum+" 种K组合方式");
	      }
		
		private void backtrack(int t){
			 if(t>k-1) { print();return;}
			 
			 else{
				 for(int i=t;i<n;i++){
					 
					if(bound(i)&&constraint(t,i)){
				    	 x[i]=1;
						 result[t]=i+1;
						 backtrack(t+1);
					     x[i]=0;
					 }
				 }
			}
		}
		
		//被访问过,则返回false
		private boolean bound(int t){
			 if(x[t]==1)return false;
			 return true;
		} 
		//从大到小的顺序, 去重。
		private boolean constraint(int t,int i) {
		   
		  if(t>0&&(result[t-1]>i+1)) return false;
		 	return true;
		}
		
	    public void print(){
			sum++;
			for(int i=0;i<k;i++)
				System.out.print(result[i]+" ");
			System.out.print("\n");
			
		}
}


类型二:含重复数的K组合问题

(不会,以后再来写。)


java完整链接:链接:https://pan.baidu.com/s/1o8IFJHg 密码:7md7




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值