排列組合算法


排列和組合是組合學最基本的概念。

組合,則是指從給定的若干個元素中取出指定個數的元素,不考慮順序。

排列,就是指從給定的若干個元素中取出指定個數的元素,並且要考慮順序。

總之,排列與元素的順序有關,組合與元素的順序無關。例如:abc和bca是同一個組合,但卻是兩個排列。

組合

1.最容易想到的,一個集合里取n個元素進行組合。

代碼如下:

import java.util.Arrays;
/**
* 模擬進制:一個集合里取n個元素進行組合
* @author Jeby
*
*/
public class CombineOfn {
public static void main(String[] args) {
String[] s = {"a", "b", "c", "d", "e"};
combine(s,3);
}

public static void combine(String[] s, int n) {
int[] dig = new int[s.length]; //進位用數組
StringBuilder state = new StringBuilder();
for (int i=s.length-1, j=0; i>=0; i--, j++) { //初始化進位數組狀態
if (s.length-i>n) { //如s有5個元素,n為2,即取2個元素組合
dig[i] = 0; //那么初始狀態為 00011
}
else {
dig[i] = 1;
}
state.append(dig[i]);
}
String max = state.toString(); //獲取進位的最大狀態,如上面的假設 11000
String min = state.reverse().toString(); //獲取進位的最小狀態,即數組初始狀態 00011
while (max.compareTo(min) >= 0) { //當最小狀態比不大於最大狀態的時候循環
if (min.length()-min.replaceAll("1", "").length() == n) { //當進位狀態中
for (int i=0; i<s.length; i++) { //1的個數為n時打印
if (dig[i] == 1) {System.out.printf("%s ", s[i]);}
}
System.out.println();
}
dig[dig.length-1]++; //模擬進位,末位+1
for (int i=dig.length-1; i>0; i--) {
if (dig[i] == 2) { //當某位進位位置達到最大狀態時
dig[i] = 0; //清0
dig[i-1]++; //往前進位
} else {
break; //不滿足進位 break
}
}
min = Arrays.toString(dig).replaceAll("\\D+", ""); //重新獲得進位狀態
}
}
}

2.迭代一個集合的全部組合。

例如,[a,b,c]的全部組合為[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]

代碼如下:

import java.util.ArrayList;
import java.util.List;
/**
* 迭代全部組合
*
* 【效果】
* 原序列:
*[a, b, c]
*全部組合序列:
*[[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]]
* @author Jeby
*
*/
public class Combinations {
/**
* 取組合方法
* 參數: list原始數組
* 返回: 包含所有組合數組的數組
*/
public static List<List<Object>> getCombinations(List<Object> list) {
List<List<Object>> result = new ArrayList<List<Object>>();
List<Object> combine = null;
long n = (long)Math.pow(2,list.size());
for (long li=0L; li<n; li++) {
combine = new ArrayList<Object>();
for (int i=0; i<list.size(); i++) {
if ((li>>>i&1) == 1)
combine.add(list.get(i));
}
result.add(combine);
}
return result;
}
/**
* 測試
*/
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<Object>();
list.add("a");
list.add("b");
list.add("c");
List<List<Object>> result = getCombinations(list);
System.out.println("原序列:");
System.out.println(list.toString());
System.out.println("全部組合序列:");
System.out.println(result.toString());
}

}

3.多個集合中分別取出一個元素進行組合。

代碼如下:

/**
* 模擬進制:多個集合中分別取出一個元素進行組合
* @author Jeby
*
*/
public class CombinateByte {
public static void main(String[] args) {
String[][] s = {{"a","b"}, {"c", "d", "e"}, {"f", "g"}};
combie(s);
}

private static void combie(String[][] s) {
int[] dig = new int[s.length]; //用來模擬進位
while (dig[0] < s[0].length) { //進位最高位不滿最大的時候循環
for (int i=0; i<s.length; i++) {
System.out.print(s[i][dig[i]]); //打印每個數組的當前進位位置的元素
}
System.out.println(); //換行
dig[dig.length-1]++; //模擬進位,末位+1
for (int i=dig.length-1; i>0; i--) {
if (dig[i] == s[i].length) { //當某進位位置達到最大時往前進位
dig[i] = 0; //當前位清0恢復最小狀態
dig[i-1]++; //進位
} else {
break; //不滿足進位時break
}
}
}
}

}

排列

1.獲得集合全排列的一個實現算法。

代碼如下:

import java.util.Arrays;

/**
* 獲得數組全排列的一個實現算法
*
*/
public class TestAllP {
static String[] array = { "x", "y", "z" };

public static void main(String[] args) {
getAllOrder(array,0,array.length - 1);
}

public static void getAllOrder(Object[] arr,int begin, int end) {
if (begin == end) {
check();
} else {
for (int i = begin; i <= end; i++) {
swap(arr,begin, i);
getAllOrder(arr,begin + 1, end);
swap(arr,i, begin);
}
}
}

/**
* 這里應該加上各種防止無效交換的情況,比如位置相同,或者2個位置的數據相同
*/
public static void swap(Object[] arr,int from, int to) {
if (from == to) {
return;
}
Object tmp = arr[from];
arr[from] = arr[to];
arr[to] = tmp;
}

/**
* 排列拿到了,可以進行進一步的篩選了。
*/
public static void check() {
System.out.println(Arrays.toString(array));
}
}

2.獲得一個集合中若干個元素的排列,可以結合從一個集合里取n個元素進行組合然后再對每一組組合數據進行全排列,在此不再累述。

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合公式及排列組合算法
 
粤ICP备14056181号  © 2014-2020 ITdaan.com