Generating M different random numbers (one at a time) from a given range 0..N-1 is less than O (M) memory

Is there any way to do this?

I mean, we can’t even work with the "in" array from {0,1, .., N-1} (because this is at least O (N) memory).

M may be = N. N may be> 2 ^ 64. The result should be uniformly random and it would be better to be any possible sequence (but cannot).

Full-fledged PRNGs (and friends) are also not suitable, since each time it will give the same sequence.

The complexity of time does not matter.

+4
source share
3 answers

, , . .

, M {0, ..., N-1} i i. p(i, M, N). , , Latex, p; , .

p(0, M, N), , M N . (.. 0...N-1) ; , , . .

MCN M N. MCN-1 . ( M - N-1, M - , ). , M-1CN-1 (.. M-1 - N-1 -set, ).

MCN; C.

, p(0, M, N) - M-1CN-1/MCN. MCN = N!/(M!*(N-M)!), M/N. , if M == N, 1 (M N ).

, , , . , , , , . , , :

w(x, y) => true with probability X / Y; otherwise false.

w , .

:

Generate a random M-selection from the set 0...N-1
Parameters: M, N

Set i = 0
while M > 0:
  if w(M, N):
     output i
     M = M - 1
  N = N - 1
  i = i + 1

, , , :

  • output i M , M, while , M 0
  • M N, , M . - , M == N, , 0.
  • i , N , 0...N-1. , ; N-1 i, . , , .

O(N+M), O(N). N , , , , .

+3

PRNG, , . Tausworthe. , , .

+1

: , 0 < M <= N-. nextRandom (N) - , [0..N):

init() {
        for (int idx = 0; idx < N; idx++) {
            a[idx] = -1;
        }
        for (int idx = 0; idx < M; idx++) {
            getNext();
        }
    }

    int getNext() {
        for (int idx = 1; idx < M; idx++) {
            a[idx -1] = a[idx];
        }
        while (true) {
            r = nextRandom(N);
            idx = 0;
            while (idx < M && a[idx] != r) idx++;
            if (idx == M) {
                a[idx - 1] = r;
                return r;
            }
        }
    }

O (M): . nextRandom(), [0..1):

rnd(0, 0, N, M); // to get next M distinct random numbers

int rnd(int idx, int n1, int n2, int m) {
    if (n1 >= n2 || m <= 0) return idx;
    int r = nextRandom(n2 - n1) + n1;
    int m1 = (int) ((m-1.0)*(r-n1)/(n2-n1) + nextRandom()); // gives [0..m-1]
    int m2 = m - m1 - 1;
    idx = rnd(idx, n1, r-1, m1);
    print r;
    return rnd(idx+1, r+1, n2, m2);
}

, r [0..N) , N1 N2 (N1 + N2 == N-1). [0..r], N1 [r + 1..N) ( N2), M1 M2 (M1 + M2 == M-1), M1/​​M2 == N1/N2. M1 M2 , , (1,2 1 p = 0,8 2 p = 0,2 ..).

0

All Articles