382. 鏈表隨機節點

題目描述:
給定一個單鏈表,隨機選擇鏈表的一個節點,並返回相應的節點值。保證每個節點被選的概率一樣。
進階:
如果鏈表十分大且長度未知,如何解決這個問題?你能否使用常數級空間複雜度實現?
思路:
蓄水池抽樣:(數學上可以證明,這裏不做證明)
從N個數中抽取k個數,N很大,k個數被抽中概率一樣。
方法:

  1. 先初始化一個集合,集合中有k個元素,將此集合作爲蓄水池。
  2. 從第k+1個元素開始遍歷,以概率是k/k+1換掉前k個數中的任意一個。
  3. 一直走下去,直到數據結束,最後存起來的k個數被抽中的概率一樣。
from random import random
listz = [N個數]
list1 = [前k個數]         # 前k的數的索引是[0,k-1]
for i in range(k to N):  # 從第k+1個數開始遍歷,i是索引
    m = randint(1, i+1)  
    if( m < k)  # k / (i+1)
        list1[m],listz[i] = list1[m],listz[i]   

代碼實現(k=1):

class Solution(object):
    def __init__(self, head):
        self.head = head
    def getRandom(self):
        count, res = 1, self.head.val
        cur = self.head.next
        while cur:
            if random.randint(1,count+1) <= 1:
                res = cur.val
            count, cur = count + 1, cur.next
        return res
class Solution(object):
    def __init__(self, head):
        self.head = head       
    def getRandom(self):
        count, res = 1, self.head.val
        cur = self.head.next
        while cur:
            if random.random()*(count+1) <= 1:
                res = cur.val
            count, cur = count + 1, cur.next
        return res

以上兩個代碼都可以,只要保證遍歷到第i個數時,以概率k/i換掉前k個數中的一個數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章