下面是关于如何用Java实现排列组合算法的完整攻略:
排列组合算法实现
什么是排列与组合
排列是指选出m个元素,一次排成一个列,有序的称为$m$的排列,记为$A_m^n$
组合是指选出m个元素,无序的称为${m}$的组合,记作$C_m^n$
可以发现,排列与组合的关联非常大,在代码实现中,它们也是联系在一起的。
排列算法实现
递归算法
通过递归实现简单,下面为排列递归实现代码:
public static void permutation(char[] arr, int start, int end) {
if (start == end) {
System.out.println(Arrays.toString(arr));
} else {
for (int i = start; i <= end; i++) {
swap(arr, start, i);
permutation(arr, start + 1, end);
swap(arr, start, i);
}
}
}
public static void swap(char[] arr, int i, int j) {
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
该算法的时间复杂度为$O(n!)$,极其耗时。
非递归算法
非递归算法采用字典序法,可以将排列算法的时间复杂度降低到$O(n^2)$。
核心代码如下:
public static void nonRecPermutation(char[] arr) {
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
while (true) {
int i, j;
// 找到逆序区域的头部(在末尾找到第一个升序的元素)
for (i = arr.length - 2; i >= 0; i--) {
if (arr[i] < arr[i + 1]) {
break;
}
if (i == 0) {
return;
}
}
// 找到头部后面的最小升序元素
for (j = arr.length - 1; j > i; j--) {
if (arr[j] > arr[i]) {
break;
}
}
// 交换头尾元素
swap(arr, i, j);
// 翻转逆序区域
reverse(arr, i + 1, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
public static void reverse(char[] arr, int start, int end) {
while (start < end) {
swap(arr, start, end);
start++;
end--;
}
}
组合算法实现
组合算法首先有一个求$C_n^m$的公式:
$$C_n^m=\frac{n!}{(n-m)!m!}$$
其实我们不必求出所有的组合,只需要找到第$k$个组合就行了,可以使用递归实现。
组合的递归实现代码如下:
public static void combination(char[] arr, int m, int start, char[] result, int index) {
if (index == result.length) {
System.out.println(Arrays.toString(result));
} else {
for (int i = start; i <= arr.length - m + index; i++) {
result[index] = arr[i];
combination(arr, m, i + 1, result, index + 1);
}
}
}
该算法的时间复杂度为$O(C_n^m)$。
示例
下面为排列和组合的示例代码:
public static void main(String[] args) {
char[] arr = {'a', 'b', 'c'};
// 排列
permutation(arr, 0, arr.length - 1);
nonRecPermutation(arr);
// 组合
char[] result = new char[2];
combination(arr, 2, 0, result, 0);
}
以上就是用Java实现排列组合算法的方法,包括排列的递归和非递归实现以及组合的递归实现。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何用Java实现排列组合算法 - Python技术站