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.
- Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
- Find the largest index l greater than k such that a[l] > a[k].
- Swap the value of a[k] with that of a[l].
- 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;
}