Java中的排列組合(三)
關於組合,目前我沒有更好的辦法,只能在排列的基礎上求解。從排列的結果中,把重複的組合去除。從n個不同元素中選取m個元素進行排列,其中的每種組合都重複了,重複的次數就是m的全排列數。比如,從1, 2, 3三個元素中選取2個元素進行排列,排列的結果是[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]。1和2這一對組合,在排列結果中出現了2次,[1, 2]和[2, 1]。所以,把從n個不同元素中選取m個元素的組合數記作C(n, m),則有如下關係:
C(n, m) = A(n, m) / A(m, m)
代碼如下:
/**
* 計算從n個不同元素中選取m個元素的組合數
* n, m應滿足如下條件:n > 0 且 0 < m <= n
* 若n, m 不能滿足上述條件,則會拋出ArithmeticException異常
*/
public static int numberOfCombination(int n, int m) {
return numberOfPermutation(n, m) / numberOfPermutation(m, m);
}
/**
* 計算從數組a中選取m個元素的組合數
* a, m應滿足如下條件:a.length > 0 且 0 < m <= a.length
* 若a, m 不能滿足上述條件,則會拋出ArithmeticException異常
*/
public static int numberOfCombination(int[] a, int m) {
return numberOfCombination(a.length, m);
}
/**
* 從數組a中選取m個元素,以二維數組的形式返回其組合
*/
public static int[][] combination(int[] a, int m) {
// 取得從數組a中選取m個元素的排列結果
int[][] temp = permutation(a, m);
// 取得從數組a中選取m個元素的組合數
int noc = numberOfCombination(a, m);
// 初始化結果數組result
int[][] result = new int[noc][m];
// 取得二維數組(排列結果)的每一行作爲一維數組,對其進行排序
for (int[] t : temp) {
Arrays.sort(t);
}
// 去除二維數組(經過行排序的排列結果)的重複行,結果存入result
for (int i = 0, j = 0; i < temp.length; i++) {
if (!contains(result, temp[i])) {
result[j] = temp[i];
j++;
}
}
return result;
}
/**
* 二維數組a中是否包含一維數組x
* @param a
* @param x
* @return
*/
public static boolean contains(int[][] a, int[] x) {
boolean result = false;
for (int[] t : a) {
if (equals(t, x)) {
result = true;
}
}
return result;
}
/**
* 測試a, b兩個一維數組的內容是否完全相同
*/
public static boolean equals(int[] a, int[] b) {
if (a.length != b.length) {
return false;
}
boolean result = true;
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
result = false;
}
}
return result;
}