基本問題是這樣的:當咱們扔一個骰子的時候是等機率的出現數字。那這個問題容易模擬。但咱們能不能模擬不等機率的骰子呢。git
給定一組序列 l = [(4,0.4),(3,0.3),(2,0.2),(1,0.1)]。github
對應數字:出現機率dom
基於此最簡單的思路 看代碼。code
def random_distr(l): r = random.uniform(0, sum([x[1] for x in l])) s = 0 for num,(item, prob) in enumerate(l): s += prob if s >= r: return num return l[-1]
思路很明確了。隨機一個數n(假定0-1之間),而後從0開始加l的機率指導大於n爲止。orm
弊端
get
這個方法的複雜度是 空間複雜度是O(N),時間複雜度是O(N)。顯然不是最好解。it
很容易想到的思路是將機率映射到key。就是尋找機率分母的最小公倍數lcm。io
如: (4,4),(3,3),(2,2),(1,1) ps:10是明顯的lcm。form
那麼對應到key 就是方法
4444 333 22 1
那麼對於該問題用一個dict,[1..10]爲key,以上爲value。那麼隨機的過程變爲,隨機一個數(1-10),而後找到對應的value。此時時間複雜度 爲O(1),空間複雜度最好O(N),最壞則O(最小公倍數) 。
這裏別人提出了個二維的維度來思考問題。
好比權重爲 10,20,30,40. key 爲ABCD.
則爲
10 AAAAAAAAAA 20 BBBBBBBBBB BBBBBBBBBB 30 CCCCCCCCCC CCCCCCCCCC CCCCCCCCCC 40 DDDDDDDDDD DDDDDDDDDD DDDDDDDDDD DDDDDDDDDD
分割並從新安排後。
AAAAAAAAAA DDDDDDDDDDDDDDD -- 10 A + 15 D = 40% A + 60% D BBBBBBBBBBBBBBBBBBBB DDDDD -- 20 B + 5 D = 80% B + 20% D CCCCCCCCCCCCCCCCCCCCCCCCC -- 25 C = 100% C DDDDDDDDDDDDDDDDDDDD CCCCC -- 20 D + 5 C = 80% D + 20% C
那麼隨機的過程變爲了,隨機一個數字 n 好比1,隨機一個0-1的機率x。那麼若是x > 0.4 ,則爲d,若是小於則爲a。
這樣空間負責爲O(N),時間複雜度爲O(1).
參考:
http://www.keithschwarz.com/darts-dice-coins/
代碼連接:
https://github.com/BigAN/sampling-according-to-probability-distributio...