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。
证明同样可以用归纳法。