洗牌演算法shuffle

2021-07-11 12:31:49 字數 2186 閱讀 4580

對這個問題的研究始於一次在群裡看到朋友發的洗牌面試題。當時也不知道具體的解法如何,於是隨口回了一句:每次從剩下的數字中隨機乙個。過後找相關資料了解了下,洗牌演算法大致有3種,按發明時間先後順序如下:

一、fisher–yates shuffle

演算法思想就是從原始陣列中隨機抽取乙個新的數字到新陣列中。演算法英文描述如下:

python實現**如下:

#

fisher–yates shuffle

'''1. 從還沒處理的陣列(假如還剩k個)中,隨機產生乙個[0, k]之間的數字p(假設陣列從0開始);

2. 從剩下的k個數中把第p個數取出;

3. 重複步驟2和3直到數字全部取完;

4. 從步驟3取出的數字序列便是乙個打亂了的數列。

'''import

random

defshuffle(lis):

result =

while

lis:

p =random.randrange(0, len(lis))

lis.pop(p)

return

result

r = shuffle([1, 2, 2, 3, 3, 4, 5, 10])

print(r)

二、knuth-durstenfeld shuffle

knuth 和durstenfeld 在fisher 等人的基礎上對演算法進行了改進。每次從未處理的資料中隨機取出乙個數字,然後把該數字放在陣列的尾部,即陣列尾部存放的是已經處理過的數字。這是乙個原地打亂順序的演算法,演算法時間複雜度也從fisher演算法的o(n

2)提公升到了o(n)。演算法偽**如下:

以下兩種實現方式的差異僅僅在於遍歷的方向而已。下面用python實現前乙個:

#

knuth-durstenfeld shuffle

defshuffle(lis):

for i in range(len(lis) - 1, 0, -1):

p = random.randrange(0, i + 1)

lis[i], lis[p] =lis[p], lis[i]

return

lisr = shuffle([1, 2, 2, 3, 3, 4, 5, 10])

print(r)

三、inside-out algorithm

knuth-durstenfeld shuffle 是乙個in-place演算法,原始資料被直接打亂,有些應用中可能需要保留原始資料,因此需要開闢乙個新陣列來儲存打亂後的序列。inside-out algorithm 演算法的基本思想是設一游標i從前向後掃瞄原始資料的拷貝,在[0, i]之間隨機乙個下標j,然後用位置j的元素替換掉位置i的數字,再用原始資料位置i的元素替換掉拷貝資料位置j的元素。其作用相當於在拷貝資料中交換i與j位置處的值。偽**如下:

python**實現如下:

#

inside-out algorithm

defshuffle(lis):

result =lis[:]

for i in range(1, len(lis)):

j =random.randrange(0, i)

result[i] =result[j]

result[j] =lis[i]

return

result

r = shuffle([1, 2, 2, 3, 3, 4, 5, 10])

print(r)

四、後話

前面用python實現了三種洗牌演算法,其實python random模組也有個shuffle方法,用法如下:

其內部實現正是使用knuth-durstenfeld shuffle演算法,不信您看**:-):

參考:from: 

洗牌演算法shuffle

原文 一 fisher yates shuffle 演算法思想就是從原始陣列中隨機抽取乙個新的數字到新陣列中。fisher yates shuffle 1.從還沒處理的陣列 假如還剩k個 中,隨機產生乙個 0,k 之間的數字p 假設陣列從0開始 2.從剩下的k個數中把第p個數取出 3.重複步驟2和3...

三種洗牌演算法shuffle

由抽牌 換牌和插牌衍生出三種洗牌演算法,其中抽牌和換牌分別對應fisher yates shuffle和knuth durstenfeld shhuffle演算法。最早提出這個洗牌方法的是 ronald a.fisher 和 frank yates,即 fisher yates shuffle,其基...

go實現陣列切片洗牌函式Shuffle

在深度學習 機器學習中,我們經常會使用到乙個叫shuffle函式,我一般叫打亂函式,也有人叫洗牌函式,就是聽著高階點,它可以幫助我們打亂資料集,那麼在go中我們如何實現乙個呢?大家可以直接使用我寫的乙個工具庫 lodago,有點lodash的味道。對於打亂函式有很多演算法實現,由於我的場景並不需要實...