$n$ is a run-time variable chosen each time the user runs the implementation.
One way I can think is to use any block cipher, say AES, as a seeded CSPRNG to randomly shuffle list of numbers $0, 1, \ldots, 2^n-1$. This way I guarantee collision-freeness up to $2^n$ numbers. But this approach is too expensive as it will require me to swap $2^n$ numbers.
Another way I can think of is to use the block cipher to generate ciphertext $c = \mathrm{enc}(\mathrm{0x000}\ldots, \mathrm{key})$, where $\mathrm{len}(c) \ge n$. Then take the 1st $n$ many bits of $c$; let's call it $c_n$. Then do: $c_n \oplus 0, c_n \oplus 1, \ldots, c_n \oplus 2^n-1$. This is efficient, but the problem is that, i think, the sequence is not random. E.g. $c_n \oplus 0$ is generally going to be closer to $c_n \oplus 1$ than, say, $c_n \oplus 100$.
The question: Is any faster approach, where I can use any block cipher for about once only, to generate the next number, such that, as I repeat the process, I get $2^n$ many unique numbers without collisions?
In a sense, I guess I may call it: an online version of shuffling the numbers $0, 1, \ldots, 2^n-1$, without needing to maintain a list in memory that is $2^n$ long.
Ideally, if the perfect online shuffle is found, it must have this distribution (where $i$ is any number in $\{0, 1, \ldots, 2^n-1\}$ and $N_j$ is a random variable that will take the value of a number in that set in the $j^{th}$ call of the ideal on-line shuffler):
$$\begin{split}
\Pr(N_0 = i) &= 1/2^n \\
\Pr(N_1 = i) &= 1/(2^n - 1) \\
\Pr(N_2 = i) &= 1/(2^n - 2) \\
\vdots & \\
\Pr(N_{2^n-1} = i) &= 1/(2^n - (2^n-1)) = 1\\
\end{split}$$