排列组合子集合的算法

import  java.util.ArrayList;
import  java.util.Arrays;
import  java.util.LinkedList;
import  java.util.List;
import  java.util.Queue;

/**
 * 
 * 
@author  Daniel
 * 排列、组合公共操作应用类
 *
 
*/
public   class  MyArraysUtil {
    
public   static   void  main(String[] args) {
        String array[] 
=  { " 0 " , " 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " , " 8 " , " 9 " };
        
// testSubArray();
        testPerm(array, 3 );
        
// 递归法测试
        testDaffodil(array, 3 );
    }
    
    
/** ************  非递归排列测试  *************** */
    
public   static   void  testPerm(Object[] array, int  m){
        
long  t1  =  System.currentTimeMillis();
        Object[] arr 
=  subArraysByLength(array,m);
        
        List
< Object[] >  list  =   new  ArrayList < Object[] > ();
        
for  ( int  i  =   0 ; i  <  arr.length; i  ++ ){
            list.add(perm((Object[])arr[i]));
        }
        Object[] _arr 
=  (Object[])list.toArray( new  Object[list.size()]);
        System.out.println(Arrays.deepToString(_arr));
        
long  t2  =  System.currentTimeMillis();
        System.out.println(
" 非递归一共有 "   +  _arr.length  +   " 个全排列集合. " );
        System.out.println(
" 非递归一共用时 "   +  (t2 - t1)  +   " 毫秒. " );
    }
    
    
/** ************************************************************ */
    
/** *******************  排列组合的应用:水仙花数   **************** */  
    
/** ************************************************************ */
    
public   static   void  testDaffodil(Object[] array, int  m){
        
long  t1  =  System.currentTimeMillis();
        Object[] arr 
=  subArraysByLength(array,m);
        List
< Object[] >  list  =   new  ArrayList < Object[] > ();
        
for  ( int  i  =   0 ; i  <  arr.length; i  ++ ){
            List
< Object[] >  _list  =   new  ArrayList < Object[] > ();
            Object[] _arr 
=  (Object[])arr[i]; // [1,2,3]
            getPerm(_arr,_list);
            list.add((Object[])_list.toArray(
new  Object[_list.size()]));
        }
        Object[] rt 
=  (Object[])list.toArray( new  Object[list.size()]);
        System.out.println(Arrays.deepToString(rt));
        
long  t2  =  System.currentTimeMillis();
        System.out.println(
" 递归一共有 "   +  rt.length  +   " 个全排列集合. " );
        System.out.println(
" 递归一共用时 "   +  (t2 - t1)  +   " 毫秒. " );
    }
    
    
/** ****************** 组合(子集合)测试 ************************ */
    
public   static   void  testSubArray(){
        String array[] 
=  { " 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " , " 8 " , " 9 " , " a " , " b " , " c " , " d " , " e " , " f " };
        
long  t1  =  System.currentTimeMillis();
        Object[] arr 
=  subArraysByLength(array, 8 );
        System.out.println(Arrays.deepToString(arr));
        System.out.println(
" 一共有 "   +  arr.length  +   " 个元素. " );
        
long  t2  =  System.currentTimeMillis();
        System.out.println(
" 一共花费时间 "   +  (t2 - t1)  +   " 毫秒. " );
    }
    
    
/** ************************************************************ */
    
/** *********        以下是排列操作                    *************** */
    
/** *********************************************************** */
    
    
/** *************** 第一种方法:递归法 ******************************** */
    
/**
     * 对array中的元素全排列,结果以数组的形式保存在list中
     * 
@param  array
     * 
@param  list
     
*/
    
public   static   void  getPerm(Object[] array,List < Object[] >  list){
        perm(array,
0 ,array.length,list);
    }
    
/**
     * 用递归取排列数
     * 
@param  array
     * 
@param  m
     * 
@param  n
     * 
@param  list
     
*/
    
private   static   void  perm(Object[] array, int  m,  int  n,List < Object[] >  list){
        
if  (array  ==   null ){
            list 
=   new  ArrayList < Object[] > ();
            
return ;
        }
        
// 用array的copy进行排列
        Object[] _array  =  Arrays.copyOf(array, array.length);
        
if  (m  <  n - 1 ) {
            perm(_array, m
+ 1 , n,list);
            
for  ( int  i = m + 1 ;i < n;i ++ ) {
                Object t
= _array[m];
                _array[m]
= _array[i];
                _array[i]
= t;
                perm(_array, m
+ 1 , n,list);

                t
= _array[m];
                _array[m]
= _array[i];
                _array[i]
= t;
            }
        } 
else  {
            list.add(_array);
        }
    }
    
/** ******************  排列第二种方法:移位法 ********************** */
    
/**
     * 不重复元素数组array中的元素全排列
     * 非递归算法
     * 
@param  array
     * 
@return
     
*/
    
public   static  Object[] perm(Object[] array){
        
if  (array  ==   null   ||  array.length  <=   1 ){
            
return  array;
        }
        Queue
< ArrayWrapper >  queue  =   new  LinkedList < ArrayWrapper > ();
        
int  len  =  array.length;
        
int  cnt  =   0 ;
        queue.offer(
new  ArrayWrapper(array, 0 ));
        
while  (cnt  <  len){
            Object[] _array 
=  array;
            
if  ( ! queue.isEmpty()){
                ArrayWrapper _tmp 
=  queue.poll();
                _array 
=  _tmp.getArray();
                cnt 
=  _tmp.getSign();
            }
            
for  ( int  j  =   0 ; j  <  len  -  cnt; j  ++ ){
                ArrayWrapper _aw 
=   new  ArrayWrapper(shiftLeft(_array,len  -  cnt,j),cnt + 1 );
                queue.offer(_aw);
            }
            cnt 
++ ;
        }
        
int  total  =  queue.size();
        Object[] result 
=   new  Object[total];
        
for  ( int  i  =   0 ; i  <  total; i  ++ ){
            result[i] 
=  queue.poll().getArray();
        }
        
return  result;
    }
    
/*
     * 有序数组array中的左起m个元素左移n位,最高位回到最低位
     
*/
    
private   static  Object[] shiftLeft(Object[] array, int  m, int  n){
        
if  (array  ==   null   ||  array.length  <=   1 ){
            
return  array;
        }
        
if  (m  <=   1 ){
            
return  array;
        }
        
int  length  =  array.length;
        Object[] _temp 
=   new  Object[length];
        
int  _n  =  n  %  m;
        System.arraycopy(array, _n, _temp, 
0 , m - _n);
        System.arraycopy(array, 
0 , _temp, m - _n, _n);
        System.arraycopy(array, m, _temp, m, length
- m);
        
        
return  _temp;
    }
    
    
/** ************************************************************** */
    
/** ************        以下是组合算法及应用 ************* */
    
/** ************************************************************** */
    
    
/** ******  array中含有eleNum个元素的所有子集****** */        
    
/**
     * 取得集合array的所有长度为eleNum的子集合
     * 若eleNum<0则取得所有子集合
     * 
@param  array
     * 
@param  length
     * 
@return
     
*/
    
public   static  Object[] subArraysByLength(Object[] array, int  eleNum){
        
if  (array  ==   null ){
            
return   null ;
        }
        
int  length  =  array.length;
        List
< Object[] >  list  =   new  ArrayList < Object[] > ();
        
for  ( int  i  =   0 ; i  <  ( 1   <<  length); i  ++ ){
            
if  ( ! (eleNum  <   0   ||  get1Cnt(i)  ==  eleNum)){
                
continue ;
            }
            List
< Object >  _list  =   new  ArrayList < Object > ();
            
for  ( int  j  =   0 ; j  <  length; j  ++ ){
                
if ((i & ( 1 << j))  !=   0 ){
                    _list.add(array[j]);
                }
            }
            list.add(_list.toArray(
new  Object[_list.size()]));
        }
        
        
return  list.toArray( new  Object[list.size()]);
    }
    
/**
     * 取得二进制正整数中"1"的个数
     * 
@param  num
     * 
@return
     
*/
    
private   static   int  get1Cnt( int  num){
        
int  cnt  =   0 ;
        
for  (;num  >   0 ;num  >>=   1 ){
            cnt 
+=  (num & 1 );
        }
        
        
return  cnt;
    }
}

/**
 * array数组封装类,加了个标签sign
 * 
@author  Daniel
 *
 
*/
class  ArrayWrapper{
    
private  Object[] array;
    
private   int  sign;
    
    
public  ArrayWrapper(Object[] array, int  sign){
        
this .array  =  array;
        
this .sign  =  sign;
    }
    
public  Object[] getArray() {
        
return  array;
    }
    
public   int  getSign() {
        
return  sign;
    }
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值