choose k samples randomly from stream
Randomly choosing k samples from a list of n items, where n is either a very large or unknown number. We are given a big array (or stream) of numbers (to simplify), and we need to write an efficient function to randomly select k numbers where 1 <= k <= n. Let the input array be stream[].
How does this work?
Case 1: For last n-k stream items, i.e., for stream[i] where k <= i < n
for item i in (k,n), it’s chosen P = k / i,
then for item i+1 not choose same as i: P=i/i+1,
then for item i+2 not choose same as i : P=i+1/i+2
So for item in (k,n), P = k/i (i/i+1) (i+1/i+2) * … (n-1/n) = k/n
Case 2: For first k stream items, i.e., for stream[i] where 0 <= i < k
The first k items are initially copied to reservoir[] and may be removed later
for item in (0,k), it’s not chosen to be replaced P=(k/k+1) (k+1/k+2) … * (n-1/n) = k/n
1 |
public int[] selectK(int[] nums,int k) { |
398. random pick index
Given an array of integers with possible duplicates, randomly output the index of a given target number. You can assume that the given target number must exist in the array.
Note:
The array size can be very large. Solution that uses too much extra space will not pass the judge.
Example:
1 |
int[] nums = new int[] {1,2,3,3,3}; |
1 |
class { |
Select a random number from stream, with O(1) space
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 stream, so can’t store the previously seen numbers.
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.
1 |
int count = 0; |
Weighted Random Sampling
Random choose an element from a dict based on frequency
1 |
Let following be the given numbers. |
Using array and binary search:
1 |
public int weightedSelect(int[] nums, int[] freq) { |
Using TreeMap:
1 |
public int weightedSelect(int[] nums, int[] freq) { |
Shuffle Array
Given an array, write a program to generate a random permutation of array elements.
The idea is to start from the last element, swap it with a randomly selected element from the whole array (including last). Now consider the array from 0 to n-2 (size reduced by 1), and repeat the process till we hit the first element.
Following is the detailed algorithm
1 |
To shuffle an array a of n elements (indices 0..n-1): |
1 |
public void shuffle(int[] nums) { |
For position i:
(1) i is not swapped after shuffle = P(i is not selected from n to i+1) * P(i is selected at i)
P = (n-1/n n-2/n-1 … i/i+1) (1/i) = 1/n
(2) i is replaced by j P(j is at i):
- j < i. P = P(i not selected from n to i+1) P(j is selected when i) = (n-1/n n-2/n-1 … i/i+1) * (1/i) = 1/n
- j>i. P = P(j not selected from n to j+1) P(i is selected when j) = (n-1/n n-2/n-1 … j/j+1) * (1/j) = 1/n
For conclusion, all num from o to n, the possibility to at a position i is 1/n
Random pick with black list (LC710)
Given a blacklist B
containing unique integers from [0, N)
, write a function to return a uniform random integer from [0, N)
which is NOT in B
.
Optimize it such that it minimizes the call to system’s Math.random()
.
Note:
1 <= N <= 1000000000
0 <= B.length < min(100000, N)
[0, N)
does NOT include N. See interval notation).
Suppose N=10, blacklist=[3, 5, 8, 9], re-map 3 and 5 to 7 and 6.
1 |
class { |
Use random(m) to implement random(n)
Use random(5) to implement random(7)
random5() returns[1,5] equal possibility, get random7() (return [1,7])equal possibility.
random5() => [1,2,3,4,5]
5*random5() => [5,10,15,20,25]
5*random5() + random5() - 5 => [1,2,3,…,25]
then get
1 |
public int random7(){ |
LeetCode 470. Use random(7) to implement random(10)
7*rand7() + rand7() - 7 => [1,49]
then get[1,40] to get rand10()
1 |
public int rand10() { |
近期评论