那些代碼量很少卻很牛X算法——洗牌算法

?閱讀本文前纯路,請(qǐng)您先點(diǎn)擊上面的藍(lán)色字體“Android掃地僧”掩幢,“關(guān)注”后再點(diǎn)擊星標(biāo)逊拍,及時(shí)上車,優(yōu)質(zhì)干貨际邻,重磅資源第一時(shí)間送達(dá)芯丧。

首先,出一個(gè)簡(jiǎn)單的題目:有一個(gè)大小為100的數(shù)組世曾,里面的元素是從 1 到 100缨恒,怎樣隨機(jī)從里面選擇 1 個(gè)數(shù)呢?

很簡(jiǎn)單,利用 Math.random() * 100 骗露,就可以拿到一個(gè) 0 到 99 的隨機(jī)數(shù)岭佳,然后去數(shù)組找對(duì)應(yīng)的位置就行了。

下面難度提高一點(diǎn)哈萧锉! 有一個(gè)大小為100的數(shù)組珊随,里面的元素是從 1 到 100,怎樣隨機(jī)從里面選擇 50 個(gè)數(shù)呢柿隙?注意玫恳!不能重復(fù)。

如果根據(jù)上面的思路优俘,你一定想到了:是不是隨機(jī) 50 次就行了京办?

那么問(wèn)題來(lái)了,這 50 次你是不能保證都是不能重復(fù)的帆焕,對(duì)吧惭婿!

嗯,你是不是又有靈感了叶雹,弄一個(gè)數(shù)組财饥,把每一次隨機(jī)的數(shù)都放到數(shù)組里,下一次隨機(jī)就看這個(gè)數(shù)組里面有沒(méi)有這數(shù)折晦,有的話就繼續(xù)隨機(jī)钥星,直到這個(gè)數(shù)組里面有 50 個(gè)數(shù)字就停止。完美满着!

嗯谦炒,講道理的話,這樣做也沒(méi)有問(wèn)題风喇,肯定可以實(shí)現(xiàn)題目要求宁改。但是如果我們想一下,就會(huì)發(fā)現(xiàn)問(wèn)題:如果我們考慮極限魂莫,就比如拿 99 個(gè)數(shù)字(你不要跟我說(shuō):那就考慮相反的情況还蹲,拿 1 個(gè)數(shù)字,把這個(gè)數(shù)字去掉就行>耙考。< )谜喊,是不是越往后重復(fù)的概率越高,那么需要重復(fù)隨機(jī)的次數(shù)也越大倦始?

是的斗遏,小老弟,你很聰明楣号,一下子就理解了最易。我們可以看下代碼:

var idxArr = []while(idxArr.length < 99){
    let idx = parseInt(Math.random()*100)
    var time = 0
    while(idxArr.includes(idx)) {
        idx = parseInt(Math.random()*100)
        console.log('time', time++)
    }
    idxArr.push(idx);}

代碼很簡(jiǎn)單怒坯,如果隨機(jī)的數(shù)字不在數(shù)組里面炫狱,就 push 進(jìn)去藻懒,否則就重新隨機(jī)。這里用了一個(gè) times 來(lái)計(jì)算每一個(gè)數(shù)需要隨機(jī)的次數(shù)视译℃揖#可以看下輸出:

image
image

可以看到,一開始基本是沒(méi)有重復(fù)的酷含,但是到了后面最后一個(gè)鄙早,要拿到一個(gè)沒(méi)有出現(xiàn)過(guò)的隨機(jī)數(shù)需要多達(dá) 65 次。

如果你把數(shù)組再放大一點(diǎn)椅亚,結(jié)果會(huì)更加夸張限番。當(dāng)然,現(xiàn)實(shí)里不會(huì)有這么極端的情況呀舔,就像你說(shuō)的弥虐,要拿 99 個(gè)數(shù)就反過(guò)來(lái)剔除 1 個(gè)數(shù)就行了。但是呢媚赖,就算沒(méi)有 99 也可能有 50 對(duì)吧霜瘪,這個(gè)性質(zhì)還是一樣的,就是可能重復(fù)較多惧磺。

這個(gè)時(shí)候就需要換一個(gè)思路颖对,如果先將數(shù)組里面的元素打亂,那么按順序選擇前 50 個(gè)不就可以了磨隘?

是的缤底!

但我們得注意什么叫亂?

一副撲克有 54 張牌番捂,有 54! 種排列方式训堆。所謂的打亂指的是,你所執(zhí)行的操作白嘁,應(yīng)該能夠 等概率地生成 這 54! 種結(jié)果中的一種坑鱼。

所以呢,進(jìn)入主題了:洗牌算法絮缅。

原理很簡(jiǎn)單:最后一個(gè)數(shù)和前面任意 n-1 個(gè)數(shù)中的一個(gè)交換鲁沥,然后倒數(shù)第二個(gè)數(shù)和前面任意 n-2 個(gè)數(shù)中的一個(gè)交換。耕魄。画恰。依次下去就行了。

洗牌算法

直接看代碼:

public void shuffle(int[] array) {
    int length = array.length;
    Random random = new Random();
    int temp;
    while (length > 0) {
        int index = random.nextInt(length);
        temp = array[index];
        array[index] = array[length -1];
        array[length -1] = temp;
        length--;
    }
}
?
//[1,2,3,4,5,6,7,8,9]
//輸出[6 1 7 8 5 2 4 9 3 ]

在整個(gè)過(guò)程中吸奴,這個(gè)算法保證了每一個(gè)元素出現(xiàn)在每一個(gè)位置的概率是相等的允扇。

這個(gè)算法真的很牛逼很經(jīng)典缠局,而且代碼很少。

需要更多算法相關(guān)考润,請(qǐng)?jiān)诠娞?hào)回復(fù)【算法】狭园,即可獲取LeetCode算法刷題精講

image

****推****薦****閱****讀****

**1. **Android進(jìn)階資源分享(2月15日更新) ****

2.Android面試題附答案,會(huì)了起碼30K****

3. 2020年今日頭條Android面試題附答案**

image
image

點(diǎn)“在看”的都漲工資了

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锅尘,更是在濱河造成了極大的恐慌,老刑警劉巖绎谦,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異粥脚,居然都是意外死亡窃肠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門刷允,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)冤留,“玉大人,你說(shuō)我怎么就攤上這事恃锉〔笃校” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵破托,是天一觀的道長(zhǎng)肪跋。 經(jīng)常有香客問(wèn)我,道長(zhǎng)土砂,這世上最難降的妖魔是什么州既? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮萝映,結(jié)果婚禮上吴叶,老公的妹妹穿的比我還像新娘。我一直安慰自己序臂,他們只是感情好蚌卤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奥秆,像睡著了一般逊彭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上构订,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天侮叮,我揣著相機(jī)與錄音,去河邊找鬼悼瘾。 笑死囊榜,一個(gè)胖子當(dāng)著我的面吹牛审胸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卸勺,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼砂沛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了孔庭?” 一聲冷哼從身側(cè)響起尺上,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤材蛛,失蹤者是張志新(化名)和其女友劉穎圆到,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卑吭,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芽淡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豆赏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挣菲。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖掷邦,靈堂內(nèi)的尸體忽然破棺而出白胀,到底是詐尸還是另有隱情,我是刑警寧澤抚岗,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布或杠,位于F島的核電站,受9級(jí)特大地震影響宣蔚,放射性物質(zhì)發(fā)生泄漏向抢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一胚委、第九天 我趴在偏房一處隱蔽的房頂上張望挟鸠。 院中可真熱鬧,春花似錦亩冬、人聲如沸艘希。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)覆享。三九已至,卻和暖如春铜秆,著一層夾襖步出監(jiān)牢的瞬間淹真,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工连茧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留核蘸,地道東北人巍糯。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像客扎,于是被迫代替她去往敵國(guó)和親祟峦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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