2

I would like to generate a sequence of n random integers in the interval [1,n] without duplicates, i.e. a permutation of the sequence [1,2,...,n] with O(log(n)) space complexity (or a polynomial function of log(n)).

One hint is that I can assume that I have a family of l-wise uniform hash functions h : [n] -> [k] (with l<=n) such that for any y_1, y_2,..., y_l and any distinct x_1, x_2,..., x_l :

P(h(x_1) = y_1 and h(x_2) = y_2 and ... and h(x_l) = y_l) = 1/(k^l)

My first idea was to use the hash function to generate the i-th element of the sequence, i.e. x_i = h(i) , check if x_i is already used (has already been returned by the hash function for some 0<j<i) and if it's the case increment x_i by 1 and check again until x_i is a new number. My problem is I can not have a vector of booleans of size n to check if the value x_i is already used. And if I do a recursive function to get the j-th value I will need at some point O(n log2(n)) bits...

I also found here that pseudorandom generator like Linear congruential generator can be used for this kind of problem with something like x_i+1 = (a*x_i + c)%n + 1 but I am not sure to understand how to choose a for any value of n to have a period of length n. In that case the hint is not really useful except for generating the first number of the sequence thus I don't think it's the right way.

user445308
  • 21
  • 2

1 Answers1

0

Here's a fun super simple solution with constant space; when N is a power of 2 and your definition of "random" is incredibly loose (the resulting sequence will alternate between even and odd numbers).

N = power of 2
P = prime number larger than N.
S = random starting number between 0 and N-1
For i = 1 TO N
    // add our prime to the starting random number
    S += P
    // S Modulus N
    // Bitwise And N-1 works because N is a pow of 2
    T = S & (N - 1)
    //T is [0, (N-1)] => we want [1, N]
    PRINT (T + 1) 
Next I

JS

for(let N = 64, P = 73, S = N * Math.random(), i = 1; i <= N; i++) { S += P; console.log((S & (N - 1)) + 1); }

Another answer would probably be to consider all of the numbers [1, N] as leaf nodes in a tree and your Log(N) space is the size of a the path through the tree. Your solution would be a function that permutes all N paths through the tree. The way you permute the paths in a pseudo random way would basically be a Linear Feedback Shift Register type generator that has a period grater than N. https://www.maximintegrated.com/en/design/technical-documents/app-notes/4/4400.html

Louis Ricci
  • 20,804
  • 5
  • 48
  • 62