The Inverse Fast Cantor Expansion is an algorithm that finds the -th lexicographically smallest permutation of in time and space.
Algorithm 0
Lemma
For any permutation of , the lexicographical rank of among all permutations of is
- Let . Find the -th lexicographically smallest permutation of recursively.
- Applying the lemma yields that is the -th lexicographically smallest permutation of .
This algorithm solves the problem in time and space.
std::vector<int> ifce(int n, int k) {
std::vector fac(n, 1);
for (int i = 1; i < n; i++) {
fac[i] = i * fac[i - 1];
}
std::vector vis(n, true);
std::vector<int> p(n);
for (int i = 0; i < n; i++) {
p[i] = (std::views::iota(0, n) | std::views::filter([&](int j) -> bool {
return vis[j];
}) | std::views::drop(k / fac[n - i - 1])).front();
vis[p[i]] = false;
k %= fac[n - i - 1];
}
return p;
}Algorithm 1
Based on Algorithm 0, using a Fenwick Tree to maintain vis yields an algorithm that solves the problem in time and space.
std::vector<int> ifce(int n, int k) {
std::vector fac(n, 1);
for (int i = 1; i < n; i++) {
fac[i] = i * fac[i - 1];
}
FenwickTree fen(n, 1);
std::vector<int> p(n);
for (int i = 0; i < n; i++) {
p[i] = fen.select(k / fac[n - i - 1]);
fen.add(p[i], -1);
k %= fac[n - i - 1];
}
return p;
}