Given a singly linked list,returnA random node ' s value from the linked list. Each node must has the same probability of being chosen.Follow Up:whatifThe linked list is extremely large and its length are unknown to you? Could You Solve ThisEfficiently without using extra space?Example://Init a singly linked list [I/b].ListNode head =NewListNode (1); Head.next=NewListNode (2); Head.next.next=NewListNode (3); Solution Solution=Newsolution (head);//Getrandom () should return either 1, 2, or 3 randomly. Each element should has equal probability of returning.Solution.getrandom ();
Solution 1:reservior Sampling: (wiki introduction)
Reservoir sampling is a family of randomized algorithms in randomly choosing a sample of K items from a List S containing n items, where n is either a very large or unknown number. Typically n is large enough, the list doesn ' t fit into main memory.
Example:size = 1
Suppose we see a sequence for items, one at a time. We want to keep a single item in memory, and we want it to is selected at random from the sequence. If We know the total number of items (n), then the solution was easy:select an index i between 1 and n with equal probability, and keep the i-th element. The problem is, and we don't always have know n in advance. A possible solution is the following:
- Keep the first item in memory.
- When the i-th item is arrives (for ):
- With probability , keep the new item (discard the old one)
- With probability , keep the old item (ignore the new one)
So:
- When there was only one item, it was kept with probability 1;
- When there was 2 items, each of them was kept with probability 1/2;
- When there was 3 items, the third item is kept with probability 1/3, and all of the previous 2 items is also kept with PR Obability (1/2) (1-1/3) = (1/2) (2/3) = 1/3;
- By induction, it's easy-to-prove that's when there was n items, each item was kept with probability 1/n.
This problem is size=1
1 /**2 * Definition for singly-linked list.3 * public class ListNode {4 * int val;5 * ListNode Next;6 * ListNode (int x) {val = x;}7 * }8 */9 Public classSolution {Ten ListNode start; One A /** @paramhead the linked list ' s head. - Note that the head was guaranteed to was not null and so it contains at least one node.*/ - Publicsolution (ListNode head) { the This. Start =head; - } - - /**Returns A random node ' s value.*/ + Public intGetrandom () { -Random random =NewRandom (); +ListNode cur =start; A intval =Start.val; at - for(intI=1; cur!=NULL; i++) { - if(Random.nextint (i) = = 0) { -val =Cur.val; - } -Cur =Cur.next; in } - returnVal; to } + } - the /** * * Your Solution Object would be instantiated and called as such: $ * Solution obj = new solution (head);Panax Notoginseng * int param_1 = Obj.getrandom (); - */
To solve the problem of size = k See: https://discuss.leetcode.com/topic/53753/brief-explanation-for-reservoir-sampling
Problem:
- Choose
k
entries from n
numbers. Make sure each number are selected with the probability ofk/n
BASIC idea:
- Choose first and
1, 2, 3, ..., k
put them into the reservoir.
k+1
for, pick it with a probability k/(k+1)
of, and randomly replace a number in the reservoir.
k+i
for, pick it with a probability k/(k+i)
of, and randomly replace a number in the reservoir.
- Repeat until
k+i
reachesn
PROOF:
k+i
for, the probability. It is selected and would replace a number in the reservoir isk/(k+i)
- For a number in the reservoir before (let's say
X
), the probability that it keeps staying in the reservoir is
P(X was in the reservoir last time)
XP(X is not replaced by k+i)
- =
P(X was in the reservoir last time)
x ( 1
- P(k+i is selected and replaces X)
)
- =
k/(k+i-1)
x ( 1
- k/(k+i)
x 1/k
)
- =
k/(k+i)
- When
k+i
reaches n
, the probability of each number staying in the reservoir arek/n
EXAMPLE
- Choose
3
numbers from [111, 222, 333, 444]
. Make sure each number are selected with a probability of3/4
- First, choose as the
[111, 222, 333]
initial reservior
- Then choose with
444
a probability of3/4
111
for, it stays with a probability of
P(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 and
222
333
- Now all the numbers has the probability of to be
3/4
picked
leetcode:linked List Random Node