簡體   English   中英

javascript中的“彩票” - 排序算法?

[英]“lottery” in javascript - sort algorithm?

我正在嘗試理解我的帖子末尾的代碼示例,我需要幫助。 所以這應該是一個“樂透”。 所以這就是我所看到的:

for( i = 1 ; i < 50 ; i++ ){ nums[ i ] = i ; }

這里它將i的值(將在1和49之間)分配給nums數組的每個第i個元素。 所以我想這只是制作一個包含數字1到49的數組。實際上,考慮到后面的代碼,我沒有看到整行的重點。

for( i = 1 ; i < 50 ; i++ )
 {
   rand = Math.ceil( Math.random() * 49 ) ;
   temp = nums[ i ] ;
   nums[ i ] = nums[ rand ] ;
   nums[ rand ] =temp ;
 }

在這里我感到困惑。 因此,它再次運行從1到49的標准循環,並且對於49次迭代中的每一次,它:

  1. 將1到49之間的隨機數分配給“rand”

  2. 將“nums”列表的第i個值(仍然只是i,對嗎?)分配給temp(為什么?)

  3. 將隨機數分配給“nums”數組的第i個元素,因此大概如果它在i = 1,nums [i] = 1,現在而不是1,它是隨機數。

  4. 然后它將temp(這是原始值,無論如何)分配回nums數組的rand-th位置的值。

那么我在這里誤會了什么? 我不明白這一點。 這是領先的? 我讀得對嗎? 據推測,在這個結尾,數組內部的數字混亂,然后最后它只選擇前6個,這是6個“隨機”數字。 但為什么不做這樣的事情:

var nums=[];
for(i=0; i<6; i++) {
  nums[i] == Math.ceil(Math.random() * 49);
} 

隨着測試,以確保隨機數不一樣?


這是整個代碼示例:

function init()
{
 var panel = document.getElementById( "panel" ) ;
 var i , rand , temp , str , nums = [] ;
 for( i = 1 ; i < 50 ; i++ ){ nums[ i ] = i ; }
 for( i = 1 ; i < 50 ; i++ )
 {
   rand = Math.ceil( Math.random() * 49 ) ;
   temp = nums[ i ] ;
   nums[ i ] = nums[ rand ] ;
   nums[ rand ] =temp ;
 }
 str = "Your Six Lucky Numbers:<br>" ;
 for( i = 1 ; i < 7 ; i++ )
 {
   str += nums[ i ] ;
   if( i !== 6 ) { str += " - " ; }
 }
 panel.innerHTML = str;
}
document.addEventListener( "DOMContentLoaded" , init , false ) ;

該代碼應該創建一個數字數組,然后將它們混洗。 它幾乎使用了Fisher-Yates shuffle ,但並不完全。 隨機數生成中也存在錯誤。

將數字1到49放在數組中並非毫無意義,這些是以后使用的數字。 它們沒有被替換,它們只是在數組中移動。

下一個循環將對數組中的項進行洗牌,但首先讓我們看一下隨機數生成。 這種創建隨機數的方法是錯誤的:

rand = Math.ceil(Math.random() * 49); // Don't use this

Math.random()方法返回一個0 <= x < 1 將該數字乘以49然后使用Math.ceil不會產生介於1和49之間的數字,它會產生0到49之間的數字。數字0很少出現,但您不能忽略它。 生成隨機數的正確方法是:

rand = Math.floor(Math.random() * 49) + 1;

用於對數組中的項進行洗牌的代碼循環遍歷項目並隨機選擇項目以交換每個項目。 這會產生一個有偏差的shuffle,它應該使用Fisher-Yates算法:

for (i = 49 ; i >= 1 ; i--) {
  rand = Math.floor(Math.random() * i) + 1;
  temp = nums[i];
  nums[i] = nums[rand];
  nums[rand] = temp;
}

循環中的最后三行交換數組中的兩個項目。 它將一個項目的值存儲起來,將另一個項目中的值復制到第一個項目中,然后將存儲的值存儲在另一個項目中。

(對於某些項目, irand的值實際上可以相同,因此項目與自身交換。這就是算法應該如何工作,它確保項目有相同的機會停留在同一個地方作為被移動到任何其他地方的機會。)

但為什么不只是像[代碼]一樣做一些測試,以確保隨機數不一樣?

這是創建隨機數的另一種方法。 它會更有效,至少在大多數時候(它理論上可以永遠循環),但它的代碼數量大致相同。

另一個解決方案是將所有數字放在一個數組中,然后從中隨機選擇數字並將它們移動到另一個數組。 這與改組算法的原理相同,但它只需要進行足夠的混洗以使前六個項目在正確的位置(或者使用Fisher-Yates算法的最后六個項目)。 但是,從數組中刪除項目通常是一項昂貴的操作,因為需要將項目轉移到其位置之后。

這確實是一個基本的洗牌。 關鍵是要確保我們只有一個唯一的數字開頭。

這個shuffle在循環中迭代一次。

檢查唯一性需要在循環中迭代一次...對於循環中的每個元素。

對於像這樣的小循環,差異基本上是零,但一般來說,當給出兩個選項時,你應該采用計算復雜度較低的那個...但總是記得注釋代碼以向未來的開發人員解釋它!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM