Permutation in lexicographic order

To generate all permutation in lexicographic order, first sort the sequence in (weakly) increasing order (repeated elements are accepted).

The following algorithm generates the next permutation lexicographically after a given permutation. It changes the given permutation in-place.

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[l] > a[k].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the subsequence from a[k + 1] to the end.

For example, start with [1, 2, 3]:
[1, 2, 3], swap 2 and 3, [1, 3, 2], reverse [2]
[1, 3, 2], swap 1 and 2, [2, 3, 1], reverse [3, 1]
[2, 1, 3], swap 1 and 3, [2, 3, 1], reverse [1]
[2, 3, 1], swap 2 and 3, [3, 2, 1], reverse [2, 1]
[3, 1, 2], swap 1 and 2, [3, 2, 1], reverse [1]
[3, 2, 1], end

Code:

// input: [1,3,2]
// output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

function permuteLexico(elems) {
    elems.sort((a, b) => a - b);
    let res = [[...elems]];
    let k;
    function findK() {
        let k = -1;
        for (let i = 0; i < elems.length - 1; i++) {
            if (elems[i] < elems[i + 1]) k = i;
        }
        return k;
    }
    function next() {
        let l;
        for (let i = k + 1; i < elems.length; i++) {
            if (elems[i] > elems[k]) l = i;
        }
        swap(k, l);
        elems = elems.slice(0, k + 1).concat(elems.slice(k + 1).reverse());
    }
    function swap(i, j) {
        let temp = elems[i];
        elems[i] = elems[j];
        elems[j] = temp;
    }
    while ((k = findK()) > -1) {
        next();
        res.push([...elems]);
    }
    return res;
}

猜你喜欢

转载自blog.csdn.net/u014510460/article/details/82635232