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

  1. Let . Find the -th lexicographically smallest permutation of recursively.
  2. 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;
}