链表随机取值

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

你可能感兴趣的:(链表随机取值)