Learnt from LeetCode question Linked List Random Node.
Scenario:
We want to make sure each element from a group is picked out with same probability, even when dealing with a group of elements with dynamic-increasing size. This is where Reservoir Sampling algorithm come on the scene.
Algorithm Description:
Problem:
Choose k entries from n numbers. Make sure each number is selected with the probability of k/n.
Basic Idea:
- Choose
1, 2, 3, ..., kfirst and put them into the reservoir. - For
k+1, pick it with a probability ofk/(k+1), and randomly replace a number in the reservoir. - For
k+i, pick it with a probability ofk/(k+i), and randomly replace a number in the reservoir. - Repeat until
k+ireachesn
Explanation:
-
Choose
3numbers from[111, 222, 333, 444]. Make sure each number is selected with a probability of3/4 -
First, choose
[111, 222, 333]as the initial reservior -
Then choose
444with a probability of3/4 -
For
111, it stays with a probability ofP(444 is not selected)
+P(444 is selected but it replaces 222 or 333)=
1/4+3/4*2/3=
3/4 -
The same case with
222and333 -
Now all the numbers have the probability of
3/4to be picked
As to This Problem:
Description:
Given a singly linked list, return a random node’s value from the linked list. Each node must have the same probability of being chosen.
Follow up: What if the linked list is extremely large and its length is unknown to you? Could you solve this efficiently without using extra space?
Example:
1
2
3
4
5
6
7
8// Init a singly linked list [1,2,3]. ListNode head = new ListNode(1); head.next = new ListNode(2); head.next.next = new ListNode(3); Solution solution = new Solution(head); // getRandom() should return either 1, 2, or 3 randomly. Each element should have equal probability of returning. solution.getRandom();
The k here is 1, which will be a special case of Reservoir Sampling algorithm.
Code:
1 | |