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;
}
}
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;
}
}