Weighted Shuffle加權(quán)的隨機打散算法的一種實現(xiàn)

Java中的Collection.shuffle(List<?> list)是一個可以將List中的元素隨機打散的函數(shù),但是在有些場景下彩扔,我們需要打散排好序的List铣卡,比如有一組用戶可能感興趣的商品列表主经,用戶可能多次看到這個列表腻异,希望每次看到時列表的順序是不同的。這就會用到weighted shuffle算法取试,既希望進行隨機打散悬槽,又希望在shuffle的過程中能盡可能保持原有順序。

Collection.shuffle的實現(xiàn)

Java從1.2開始就引入了java.util.Collections這個類瞬浓,關(guān)于shuffle方法的實現(xiàn)是這樣描述的:

This implementation traverses the list backwards, from the last element up to the second, repeatedly swapping a randomly selected element into the "current position". Elements are randomly selected from the portion of the list that runs from the first element to the current position, inclusive.

這個實現(xiàn)將列表反轉(zhuǎn)初婆,從最后一個元素向前到第二個元素,重復(fù)隨機選取一個元素與當前位置的元素交換猿棉。被交換元素是從列表第一個元素到當前元素(包括)的這部分中隨機挑選的磅叛。

一種Weighted Shuffle算法

從shuffle擴展

我們可以從Java Collection.shuffle實現(xiàn)中交換的想法觸發(fā),擴展出一種weighted shuffle的算法铺根。在shuffle方法中宪躯,可以不嚴格地認為兩個元素是否發(fā)生交換的概率是50%,我們只要調(diào)整這個概率位迂,讓排在有序列表前面的元素與排在后面的元素交換的概率更低就可以實現(xiàn)weighted shuffle了.

比如,有序列表是一個List<WeightItem<E>>類型的,WeightItem<E>定義如下:

public class WeightItem<E> {
   private E item;
   private Double weight;
       
   public WeightItem(E item, Double weight) {
       this.item = item;
       this.weight = weight;
   }

   public E getItem() {
       returnthis.item;
   }
     
   public Double getWeight() {
       return this.weight;
   }
}

這樣就可以寫出最核心的代碼了

Collections.sort(weightItemList, new Comparator<WeightItem>(){  
  public int compare(WeightItem s1, WeightItem s2){
      return Math.random() * s1.getWeight() > Math.random() * s2.getWeight() ? -1 : 1;
  }
});

由于我們直接使用了Collections中的sort方法掂林,所以這個weighted shuffle算法的空間復(fù)雜度是O(n)臣缀,時間復(fù)雜度是O(nlogn)

概率有多大泻帮?

前面提到weighted shuffle是介于完全隨機和完全保序之間精置,兩個元素交換的概率到底有多大,我們可以算一算锣杂。

假設(shè)有序列表中兩個元素Xm和Xn脂倦,它們的權(quán)重分別是M和N,不妨設(shè)M >= N元莫,打散后Xm排在Xn后面的概率就等同于下面這個更數(shù)學(xué)化的描述:

設(shè)隨機變量m服從[0, M]之間均勻分布赖阻,隨機變量n服從[0, N]之間均勻分布,M >= N踱蠢,求p(m < n)火欧。

m可能在[0, N]之間,也可能在[N, M]之間茎截,按照條件概率分開可以寫成:

上式中第一項為0苇侵,第二項 p(m <= N)=N / M,而當m <= N時企锌,m的取值范圍與n相同榆浓,所以p(m < n | m <= N) = 1 / 2。所以:

  • 當N = M時撕攒,p(m < n) = 0.5陡鹃,元素Xm和Xn的權(quán)重相同,Weighted Shuffle退化成普通的shuffle打却,元素間的交互是完全隨機的杉适;
  • 當N = 0是,p(m < n) = 1柳击,元素Xm和Xn的順序始終可以保持猿推,不再是shuffle了。

更隨機捌肴?還是更保序蹬叭?

在對一個有序列表進行weighted shuffle的時候,我們面臨兩個方向的選擇状知,讓shuffle的結(jié)果更加隨機秽五,或者讓結(jié)果更保持原有的順序。這個問題通過對有序列表元素設(shè)置權(quán)重來完成饥悴。

如果我們只是有一個有序列表坦喘,而沒有每個元素對應(yīng)的權(quán)重盲再,有一種簡單設(shè)置權(quán)重的方法,對于排列在i位的元素瓣铣,權(quán)重為:

其中L為列表的長度答朋,alpha為控制偏向隨機還是偏向保序的參數(shù),取值范圍是[0, +infinite)棠笑。我們可以比較排列在第一位和最后一位的兩個元素在shuffle后交換順序的概率:

當列表長度越大梦碗、alpha取值越大時,概率越斜途取洪规;反之概率越大。

為了直觀展示參數(shù)的效果循捺,這里列出幾個例子:

L alpha p
5 0.01 50.8%
5 0.1 57.4%
5 1 90.0%
10 0.01 51.1%
10 0.1 60.3%
10 1 95.0%
30 0.01 98.3%
30 0.1 64.6%
30 1 51.7%

最后:還是概率

本文的算法給出兩個有序元素shuffle后的順序改變的概率是p(m<n) = N / 2M斩例,這個概率并不適用于任何情況,比如當元素的權(quán)重有比較明確可比較的含義時巨柒,我們希望這個概率是:

對于這種情況樱拴,我們只要修改weighted shuffle算法中對排序交換條件的判斷代碼就可以實現(xiàn)了,具體做法這里就不做詳細的介紹了洋满。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晶乔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子牺勾,更是在濱河造成了極大的恐慌正罢,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驻民,死亡現(xiàn)場離奇詭異翻具,居然都是意外死亡,警方通過查閱死者的電腦和手機回还,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門裆泳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人柠硕,你說我怎么就攤上這事工禾。” “怎么了蝗柔?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵闻葵,是天一觀的道長。 經(jīng)常有香客問我癣丧,道長槽畔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任胁编,我火速辦了婚禮厢钧,結(jié)果婚禮上鳞尔,老公的妹妹穿的比我還像新娘。我一直安慰自己坏快,他們只是感情好铅檩,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布憎夷。 她就那樣靜靜地躺著莽鸿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拾给。 梳的紋絲不亂的頭發(fā)上祥得,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音蒋得,去河邊找鬼级及。 笑死,一個胖子當著我的面吹牛额衙,可吹牛的內(nèi)容都是我干的饮焦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼窍侧,長吁一口氣:“原來是場噩夢啊……” “哼县踢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起伟件,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤硼啤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后斧账,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谴返,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年咧织,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗓袱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡习绢,死狀恐怖渠抹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情毯炮,我是刑警寧澤逼肯,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站桃煎,受9級特大地震影響篮幢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜为迈,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一三椿、第九天 我趴在偏房一處隱蔽的房頂上張望缺菌。 院中可真熱鬧,春花似錦搜锰、人聲如沸伴郁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽焊傅。三九已至,卻和暖如春狈涮,著一層夾襖步出監(jiān)牢的瞬間狐胎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工歌馍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留握巢,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓松却,卻偏偏與公主長得像暴浦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晓锻,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 這個不錯分享給大家歌焦,從扣上看到的,就轉(zhuǎn)過來了 《電腦專業(yè)英語》 file [fail] n. 文件带射;v. 保存文...
    麥子先生R閱讀 6,564評論 5 24
  • 回溯算法 回溯法:也稱為試探法同规,它并不考慮問題規(guī)模的大小,而是從問題的最明顯的最小規(guī)模開始逐步求解出可能的答案窟社,并...
    fredal閱讀 13,650評論 0 89
  • 隨機算法涉及大量概率論知識券勺,有時候難得去仔細看推導(dǎo)過程,當然能夠完全了解推導(dǎo)的過程自然是有好處的灿里,如果不了解推導(dǎo)過...
    __七把刀__閱讀 5,808評論 0 6
  • 1关炼、substringFromIndex,substringToIndex匣吊,substringWithRange的...
    天亮説晚安閱讀 394評論 0 0
  • “到此一游”的外星人 程安安小朋友覺得自己是一個不一般的小朋友儒拂,并且也一直認為自己是天上的神仙的女兒,在洗澡的時候...
    我還沒想好叫什么呢閱讀 328評論 0 0