Given a singly linked list, return a random node's value from the linked list. Each node must have thesame 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();
蓄水池抽样:有意思¥¥¥
链表长度是未知的,因此不能直接用random函数求值
I 当链表长度为1时,random.randint(0, 0)恒等于0,因此抽到第1个元素的概率为1
II 假设抽取前n个元素的概率相等,均为1/n
III 当抽取第n+1个元素时:
若random.randint(0, n)等于0,则返回值替换为第n+1个元素,其概率为1/(n+1);
否则,抽取的依然是前n个元素,其概率为1/n * n/(n+1) = 1/(n+1)
对于第一个数其被选择的概率为
1/1(1-1/2)(1-1/3)(1-1/4)...(1-1/n) = 1/n
.对于任意一个数i来说, 其被选择的概率为
1/i(1-1/(i+1))...(1-1/n),
import random
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
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
"""
newHead = self.head
n = 0
val = 0
while newHead != None:
if random.randint(0,n) == 0:
val = newHead.val
newHead = newHead.next
n += 1
return val
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
solution = Solution(head)
print(solution.getRandom())