打印k next按字典顺序排列n位数字的排列

时间:2017-08-26 18:21:38

标签: arrays algorithm permutation

我想按照字典顺序从给定的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排列。

1 个答案:

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