Leetcode 382. Linked List Random Node

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:

// 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();

 

本题可以用reservoir sampling来解决不明list长度的情况下平均概率选择元素的问题。

假设在[x_1,...,x_n]只选一个元素,要求每个元素被选中的概率都是1/n,但是n未知。 其中 random.randint(0, cnt) == 0: 的概率是1/(cnt+1)。reservoir sampling的证明可以使用归纳法(induction)。

 

 1 class Solution(object):
 2 
 3     def __init__(self, head):
 4         """
 5         @param head The linked list's head.
 6         Note that the head is guaranteed to be not null, so it contains at least one node.
 7         :type head: ListNode
 8         """
 9         self.head = head
10 
11     def getRandom(self):
12         """
13         Returns a random node's value.
14         :rtype: int
15         """
16         cnt = 0
17         head = self.head
18         while head:
19             if random.randint(0, cnt) == 0:
20                 ans = head.val
21             head = head.next
22             cnt += 1
23         return ans

 

本题的一个推广是如何在[x_1,...,x_n]中选出k个元素。并且每个x_i被选中的概率都一样,而且n未知。

1. if i <= k, T_i = T_{i-1}\cup x_i

2. else with p = k/i replace one element in T_{i-1} with x_i with p=1/k。

证明同样可以用归纳法。

 

posted @ 2016-12-25 04:15  lettuan  阅读(283)  评论(0编辑  收藏  举报