洗牌算法具體指的是什么

1.背景介紹

洗牌算法是我們常見(jiàn)的隨機(jī)問(wèn)題摸吠,在玩游戲、隨機(jī)排序時(shí)經(jīng)常會(huì)碰到嚎花,本質(zhì)是讓一個(gè)數(shù)組內(nèi)的元素隨機(jī)排列寸痢。 類(lèi)似于洗牌,將所有牌的位置打亂紊选,讓他們隨機(jī)出現(xiàn)在任何位置啼止。

2.知識(shí)剖析

常見(jiàn)的洗牌算法

方法一:

假如你要洗牌,那么最隨機(jī)的做法無(wú)疑是從牌堆里隨便抽一張出來(lái)兵罢,然后放在一邊献烦,之后從剩下的牌里重復(fù)之前的操作,直到所有牌都被抽出來(lái)放到了另一堆中趣些。抽象到代碼世界仿荆,按相同的做法,就是隨機(jī)從數(shù)組里取出一個(gè)元素坏平,保存到另一個(gè)數(shù)組拢操,然后重復(fù)之,直到原數(shù)組中所有元素都處理掉舶替。

Demo

function shuffle(array) {

? ? var copy = [],

? ? ? ? n = array.length,

? ? ? ? i;

? ? // 如果還剩有元素則繼續(xù)令境。。顾瞪。

? ? while (n) {

? ? ? ? // 隨機(jī)抽取一個(gè)元素

? ? ? ? i = Math.floor(Math.random() * array.length);

? ? ? ? // 如果這個(gè)元素之前沒(méi)有被選中過(guò)舔庶。。

? ? ? ? if (i in array) {

? ? ? ? ? ? copy.push(array[i]);

? ? ? ? ? ? delete array[i];

? ? ? ? ? ? n--;

? ? ? ? }

? ? }

? ? return copy;

}

方法二:

方法一的問(wèn)題在此陈醒,即使一個(gè)序號(hào)上的元素已經(jīng)被處理過(guò)了惕橙,由于隨機(jī)函數(shù)產(chǎn)生的數(shù)是隨機(jī)的,所有這個(gè)被處理過(guò)的元素序號(hào)可能在之后的循環(huán)中不斷出現(xiàn)钉跷,一是效率問(wèn)題弥鹦,另一個(gè)就是邏輯問(wèn)題了,存在一種可能是永遠(yuǎn)運(yùn)行不完爷辙!

所以改進(jìn)的做法就是處理完一個(gè)元素后彬坏,我們用Array的splice()方法將其從目標(biāo)數(shù)組中移除同時(shí)也更新了目標(biāo)數(shù)組的長(zhǎng)度,如此一來(lái)下次遍歷的時(shí)候是從新的長(zhǎng)度開(kāi)始膝晾,不會(huì)重復(fù)處理的情況了栓始。

Demo

function shuffle(array) {

? ? var copy = [],

? ? ? ? n = array.length,

? ? ? ? i;

? ? // 如果還剩有元素。血当。? ? while (n) {

? ? ? ? // 隨機(jī)選取一個(gè)元素? ? ? ? i = Math.floor(Math.random() * n--);

? ? ? ? // 移動(dòng)到新數(shù)組中? ? ? ? copy.push(array.splice(i, 1)[0]);

? ? }

? ? return copy;

}

最終版:

上面的做法已經(jīng)可以了幻赚,但上面的改進(jìn)依然還有提升空間禀忆。注意到我們要做的僅僅是將數(shù)組元素重新排序,已經(jīng)取出來(lái)的元素和剩下的元素之和一定是等于數(shù)組原來(lái)的總元素個(gè)數(shù)的坯屿。所以可以考慮不創(chuàng)建新的數(shù)組來(lái)保存已經(jīng)抽取的元素油湖,可以這樣,隨機(jī)從數(shù)組中抽出一個(gè)元素领跛,然后與最后個(gè)元素交換乏德,相當(dāng)于把這個(gè)隨機(jī)抽取的元素放到了數(shù)組最后面去,表示它已經(jīng)是被隨機(jī)過(guò)了吠昭,同時(shí)被換走的那個(gè)元素跑到前面去了喊括,會(huì)在后續(xù)的重復(fù)操作中被隨機(jī)掉。一輪操作過(guò)后矢棚,下一輪我們只在剩下的n-1個(gè)元素也就是數(shù)組的前n-1個(gè)元素中進(jìn)行相同的操作郑什,直到進(jìn)行到第一個(gè)。

Demo

Array.prototype.shuffle = function() {

? ? var input = this;

? ? for (var i = input.length - 1; i >= 0; i--) {

? ? ? var randomIndex = Math.floor(Math.random() * (i + 1));//獲取小于this.length的隨機(jī)整數(shù)? ? ? var itemAtIdex = input[randomIndex];

? ? ? input[randomIndex] = input[i];

? ? ? input[i] = itemAtIdex;//input[randomIndex]和input[i]交換值? ? }

? ? return input;

? }

3.常見(jiàn)問(wèn)題

有沒(méi)有簡(jiǎn)潔點(diǎn)的洗牌算法蒲肋?

4.解決方案

arr.sort(function(){ return 0.5-Math.random()});

結(jié)合數(shù)組自帶的sort()方法編寫(xiě),中間變量以及值交換什么的都省了,一行代碼就可以實(shí)現(xiàn)蘑拯,相對(duì)而言比較簡(jiǎn)單,但是他并不能實(shí)現(xiàn)真正意義的隨機(jī)兜粘。

var arr = [0,1,2,3,4,5,6,7,8,9];var res = [0,0,0,0,0,0,0,0,0,0];var t = 10000;for(var i = 0; i < t; i++){

? var sorted = shuffle(arr.slice(0));

? sorted.forEach(function(o,i){

? ? ? res[i] += o;

? });

}

res = res.map(function(o){

? ? return o / t;

});console.log(res);

5.編碼實(shí)戰(zhàn)

6.擴(kuò)展思考

怎么保證這個(gè)算法得到的數(shù)組是完全隨機(jī)的(即等概)申窘?

計(jì)算機(jī)本來(lái)就沒(méi)辦法實(shí)現(xiàn)真正的隨機(jī),計(jì)算機(jī)是一種可確定孔轴,可預(yù)測(cè)的的設(shè)備剃法,沒(méi)法通過(guò)一行一行的確定的代碼本身自身產(chǎn)生真隨機(jī),產(chǎn)生的所謂隨機(jī)數(shù)全部都是偽隨機(jī)路鹰,最多只能做到范圍足夠大贷洲,產(chǎn)生規(guī)律足夠復(fù)雜,感覺(jué)像是隨機(jī)而已晋柱。

7.參考文獻(xiàn)

參考一:?洗牌算法:給數(shù)組隨機(jī)排序

參考二:?由亂序播放說(shuō)開(kāi)了去

參考三:?數(shù)組的完全隨機(jī)排列

8.更多討論

PPT:https://ptteng.github.io/PPT/PPT-java/Java-1-page.html#/

騰訊視頻:https://v.qq.com/x/page/c05322a4vdf.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末优构,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子雁竞,更是在濱河造成了極大的恐慌钦椭,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浓领,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡势腮,警方通過(guò)查閱死者的電腦和手機(jī)联贩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捎拯,“玉大人泪幌,你說(shuō)我怎么就攤上這事盲厌。” “怎么了祸泪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵吗浩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我没隘,道長(zhǎng)懂扼,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任右蒲,我火速辦了婚禮阀湿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瑰妄。我一直安慰自己陷嘴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布间坐。 她就那樣靜靜地躺著灾挨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竹宋。 梳的紋絲不亂的頭發(fā)上劳澄,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音逝撬,去河邊找鬼浴骂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宪潮,可吹牛的內(nèi)容都是我干的溯警。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼狡相,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梯轻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起尽棕,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤喳挑,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后滔悉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伊诵,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年回官,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了曹宴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歉提,死狀恐怖笛坦,靈堂內(nèi)的尸體忽然破棺而出区转,到底是詐尸還是另有隱情,我是刑警寧澤版扩,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布废离,位于F島的核電站,受9級(jí)特大地震影響礁芦,放射性物質(zhì)發(fā)生泄漏蜻韭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一宴偿、第九天 我趴在偏房一處隱蔽的房頂上張望湘捎。 院中可真熱鬧,春花似錦窄刘、人聲如沸窥妇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)活翩。三九已至,卻和暖如春翻伺,著一層夾襖步出監(jiān)牢的瞬間材泄,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工吨岭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拉宗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓辣辫,卻偏偏與公主長(zhǎng)得像旦事,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子急灭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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