Given a stream of numbers, generate a random number from the stream. You are allowed to use only O(1) space and the input is in the form of a stream, so can’t store the previously seen numbers.
So how do we generate a random number from the whole stream such that the probability of picking any number is 1/n. with O(1) extra space? This problem is a variation of Reservoir Sampling. Here the value of k is 1.
1) Initialize ‘count’ as 0, ‘count’ is used to store count of numbers seen so far in stream.
2) For each number ‘x’ from stream, do following
…..a) Increment ‘count’ by 1.
…..b) If count is 1, set result as x, and return result.
…..c) Generate a random number from 0 to ‘count-1’. Let the generated random number be i.
…..d) If i is equal to ‘count – 1’, update the result as x.
C++
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
int selectRandom( int x)
{
static int res;
static int count = 0;
count++;
if (count == 1)
res = x;
else
{
int i = rand () % count;
if (i == count - 1)
res = x;
}
return res;
}
int main()
{
int stream[] = {1, 2, 3, 4};
int n = sizeof (stream) / sizeof (stream[0]);
srand ( time (NULL));
for ( int i = 0; i < n; ++i)
cout << "Random number from first " << i + 1
<< " numbers is " << selectRandom(stream[i]) << endl;
return 0;
}
|
C
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int selectRandom( int x)
{
static int res;
static int count = 0;
count++;
if (count == 1)
res = x;
else
{
int i = rand () % count;
if (i == count - 1)
res = x;
}
return res;
}
int main()
{
int stream[] = {1, 2, 3, 4};
int n = sizeof (stream)/ sizeof (stream[0]);
srand ( time (NULL));
for ( int i = 0; i < n; ++i)
printf ( "Random number from first %d numbers is %d \n" ,
i+1, selectRandom(stream[i]));
return 0;
}
|
Java
import java.util.Random;
public class GFG
{
static int res = 0 ;
static int count = 0 ;
static int selectRandom( int x)
{
count++;
if (count == 1 )
res = x;
else
{
Random r = new Random();
int i = r.nextInt(count);
if (i == count - 1 )
res = x;
}
return res;
}
public static void main(String[] args)
{
int stream[] = { 1 , 2 , 3 , 4 };
int n = stream.length;
for ( int i = 0 ; i < n; i++)
System.out.println( "Random number from first " + (i+ 1 ) +
" numbers is " + selectRandom(stream[i]));
}
}
|
Python3
import random
res = 0
count = 0
def selectRandom(x):
global res
global count
count + = 1 ;
if (count = = 1 ):
res = x;
else :
i = random.randrange(count);
if (i = = count - 1 ):
res = x;
return res;
stream = [ 1 , 2 , 3 , 4 ];
n = len (stream);
for i in range (n):
print ( "Random number from first" ,
(i + 1 ), "numbers is" ,
selectRandom(stream[i]));
|
C#
using System;
class GFG
{
static int res = 0;
static int count = 0;
static int selectRandom( int x)
{
count++;
if (count == 1)
res = x;
else
{
Random r = new Random();
int i = r.Next(count);
if (i == count - 1)
res = x;
}
return res;
}
public static void Main()
{
int [] stream = {1, 2, 3, 4};
int n = stream.Length;
for ( int i = 0; i < n; i++)
Console.WriteLine( "Random number from " +
"first {0} numbers is {1}" ,
i + 1, selectRandom(stream[i]));
}
}
|
PHP
<?php
function selectRandom( $x )
{
$res ;
$count = 0;
$count ++;
if ( $count == 1)
$res = $x ;
else
{
$i = rand() % $count ;
if (i == $count - 1)
$res = $x ;
}
return $res ;
}
$stream = array (1, 2, 3, 4);
$n = sizeof( $stream )/sizeof( $stream [0]);
srand(time(NULL));
for ( $i = 0; $i < $n ; ++ $i )
echo "Random number from first " ,
$i +1, "numbers is " ,
selectRandom( $stream [ $i ]), "\n" ;
?>
|
Javascript
<script>
let res = 0;
let count = 0;
function selectRandom(x)
{
count++;
if (count == 1)
res = x;
else
{
let i = Math.floor(Math.random()*(count));
if (i == count - 1)
res = x;
}
return res;
}
let stream=[1, 2, 3, 4];
let n = stream.length;
for (let i = 0; i < n; i++)
document.write( "Random number from first " + (i+1) + " numbers is " + selectRandom(stream[i])+ "<br>" );
</script>
|
Output
Random number from first 1 numbers is 1
Random number from first 2 numbers is 1
Random number from first 3 numbers is 1
Random number from first 4 numbers is 4
Time Complexity: O(n)
Auxiliary Space: O(1)
How does this work
We need to prove that every element is picked with 1/n probability where n is the number of items seen so far. For every new stream item x, we pick a random number from 0 to ‘count -1’, if the picked number is ‘count-1’, we replace the previous result with x.
To simplify proof, let us first consider the last element, the last element replaces the previously-stored result with 1/n probability. So the probability of getting the last element as the result is 1/n.
Let us now talk about the second last element. When the second last element processed the first time, the probability that it replaced the previous result is 1/(n-1). The probability that the previous result stays when the nth item is considered is (n-1)/n. So the probability that the second last element is picked in the last iteration is [1/(n-1)] * [(n-1)/n] which is 1/n.
Similarly, we can prove for third last element and others.
References:
Reservoir Sampling
Method 2: generate a random number from the stream with numpy random.choice() method.
C++
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
int stream[] = {1, 4, 5, 2, 7};
int length = sizeof (stream)/ sizeof (stream[0]);
srand ( time (nullptr));
int randomIndex = rand () % length;
int randomNum = stream[randomIndex];
cout << "Random number is " << randomNum << endl;
return 0;
}
|
Java
import java.util.Random;
public class Main {
public static void main(String[] args)
{
int [] stream = { 1 , 4 , 5 , 2 , 7 };
int randomIndex
= new Random().nextInt(stream.length);
int randomNum = stream[randomIndex];
System.out.println( "Random number is " + randomNum);
}
}
|
Python3
import numpy as np
stream = [ 1 , 4 , 5 , 2 , 7 ]
random_num = np.random.choice(stream)
print ( "random number is " ,random_num)
|
C#
using System;
class Program
{
static void Main()
{
int [] stream = { 1, 4, 5, 2, 7 };
Random rand = new Random();
int randomIndex = rand.Next(stream.Length);
int randomNum = stream[randomIndex];
Console.WriteLine( "Random number is " + randomNum);
}
}
|
Javascript
const stream = [1, 4, 5, 2, 7];
const randomIndex = Math.floor(Math.random() * stream.length);
const randomNum = stream[randomIndex];
console.log(`random number is ${randomNum}`);
|
Output
Random number is 2
Time Complexity: O(n)
Auxiliary Space: O(1)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
20 Apr, 2023
Like Article
Save Article