###382. Linked List Random Node
题目: https://leetcode.com/problems/linked-list-random-node/
难度:
Medium
tag:reservoir sampling 水塘抽样
思路:
n选k
这样来看,有k个元素,那么这个时候全部选中,当第k+1个元素进来的时候,生成一个随机数r,如果 r <= k,那么用它来替换第r个元素
那么r被替换掉的概率是 1 / k + 1, 不被替换掉的概率是 k / k + 1 (不生成r)
k+2来继续: 被替换掉的概率 1 / k + 2, 不被替换掉的概率 (k + 1) / (k+2)
所以最终被选中的(不被替换掉的概率是) k / n
随机 √
针对这道题目来看
- 一开始选head为choice
- 出现第二个,生成[1,2]之间的随机数,如果r = 2,则用新的来替换choice
- 出现第三个,生成[1,2,3]之间的随机数,如果r = 3,则替换
再写简单一点就是
每次以 1/i 来决定是否用新的元素来替换选中元素,那么就是 i - 1 / i 不替换,它之前被选中的概率就是 1 / i-1 ,所以最终被选中的概率是 1/i
这个对于linked list更优之处在于它不用reverse
时间复杂度 O(N), 空间复杂度O(K)
然后AC
class Solution(object):
def __init__(self, head):
"""
@param head The linked list's head.
Note that the head is guaranteed to be not null, so it contains at least one node.
:type head: ListNode
"""
self.head = head
def getRandom(self):
"""
Returns a random node's value.
:rtype: int
"""
choice = self.head
cur = self.head
i = 1
while cur.next:
cur = cur.next
i += 1
rd = random.randint(1,i)
if rd == i:
choice = cur
return choice.val