我想按照字典顺序从给定的n位数字生成下一个k排列。
给出初始数组和k。 比如让开始数组是1 2 4 3 然后接下来的3个排列 1 3 2 4: 1 3 4 2: 1 4 3 2:
我试过
static void permute(int arr[], int low, int high) {
if (low == high) {
printArray(arr);
return;
}
for (int i=low; i<high; i++) {
swap(arr, i, low);
permute(arr, low+1, high);
swap(arr, low, i);
}
}
static void swap(int arr[], int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
但这并没有按照字典顺序给出排列。而且我也无法限制下一个k排列。
答案 0 :(得分:0)
我在JAVA中创建了一个解决方案。我不得不使用BigInteger,因为当我们增加数组的长度时,排列的数量可能是天文数字。 (对于短阵列,您可以将其更改为长。)
复杂度仅为O(n * length),因此只要您不想计算数百万个排列,使用这些复杂对象就不是问题。
它还有另外两种有用的方法:
BigInteger calculatePermutationNumber(Integer[] arr)
它以此数组排列的字典顺序计算数组的位置。
Integer[] createNthPermutation(Integer[] arr, BigInteger n)
它创建给定(排序)数组的第N个排列。因此,您可以使用它来计算任何排列,而不仅仅是下一个或前一个排列。
算法本身采用以下方法:
Integer[][] createNextXPermutation(Integer[] arr, int x)
上述方法均未检查输入参数的有效性。虽然它有一个有趣的副作用:如果你使用参数调用函数,其中在词典顺序中没有剩余的排列,那么它将翻转并继续从头开始列出排列。在某些情况下可能有用。 :)
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Selindek
*/
public class Permutation {
public static void main(String... args) {
Integer[] array = new Integer[] { 1, 2, 4, 3 };
int n = 3;
Integer[][] result = createNextXPermutation(array, n);
for (int i = 0; i < n; i++) {
System.out.println(Arrays.asList(result[i]));
}
}
public static Integer[][] createNextXPermutation(Integer[] arr, int x) {
Integer[][] ret = new Integer[x][];
BigInteger n = calculatePermutationNumber(arr);
Integer digits[] = Arrays.copyOf(arr, arr.length);
Arrays.sort(digits);
for (int i = 0; i < x; i++) {
ret[i] = createNthPermutation(digits, n.add(BigInteger.valueOf(i + 1)));
}
return ret;
}
public static BigInteger calculatePermutationNumber(Integer[] arr) {
int length = arr.length;
Integer digits[] = Arrays.copyOf(arr, length);
Arrays.sort(digits);
List<Integer> list = new ArrayList<Integer>(Arrays.asList(digits));
BigInteger n = BigInteger.ZERO;
for (int i = 0; i < length - 1; i++) {
int index = list.indexOf(arr[i]);
list.remove(index);
n = n.add(BigInteger.valueOf(index));
n = n.multiply(BigInteger.valueOf(length - 1 - i));
}
return n;
}
public static Integer[] createNthPermutation(Integer[] arr, BigInteger n) {
int length = arr.length;
Integer[] ret = new Integer[length];
List<Integer> list = new ArrayList<Integer>(Arrays.asList(arr));
int[] pos = new int[length];
for (int i = 1; i <= length; i++) {
BigInteger[] div = n.divideAndRemainder(BigInteger.valueOf(i));
n = div[0];
pos[length - i] = div[1].intValue();
}
for (int i = 0; i < length; i++) {
ret[i] = list.remove(pos[i]);
}
return ret;
}
}