"彩票"在javascript中 - 排序算法?

时间:2015-08-08 23:44:19

标签: javascript arrays random

我试图理解我帖子末尾的代码示例,我需要帮助。所以这应该是一个"彩票"。所以这就是我所看到的:

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之间的随机数分配给&#34; rand&#34;

  2. 分配&#39; nums&#39;的第i个值。列表(这仍然只是我,对吗?)到temp(为什么?)

  3. 将随机数分配给&#34; nums&#34;的第i个元素。数组,所以如果它在i = 1,nums [i] = 1,现在而不是1,它就是随机数。

  4. 然后它将temp(这是原始值,无论如何)分配回nums数组的rand-th位置的值。

  5. 那么我在这里误会了什么?我不明白这一点。这是领先的?我读得对吗?据推测,在这个结束时,阵列中的数字混乱,然后最后它只选择前六个,这是6&#34;随机&#34;数字。但为什么不做这样的事情:

    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 ) ;
    

2 个答案:

答案 0 :(得分:3)

代码应该创建一个数字数组然后随机播放它们。它几乎使用了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;

用于对数组中的项进行洗牌的代码循环遍历项目并随机选择项目以交换每个项目。这会产生一个有偏差的混乱,它应该使用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的值实际上可能相同,因此项目与自身交换。这就是算法的工作方式,它确保了item与移动到任何其他地方的机会相同的机会。)

  

但为什么不只是做[代码]之类的事情以及确保测试   随机数不一样吗?

这是创建随机数的另一种方法。它会更有效率,至少在大多数时候(它理论上可以永远循环),但它的代码数量相同。

另一个解决方案是将所有数字放在一个数组中,然后从中随机选择数字并将它们移动到另一个数组。这与改组算法的原理相同,但它只需要进行足够的混洗以使前六个项目在正确的位置(或者使用Fisher-Yates算法的最后六个项目)。但是,从数组中删除项目通常是一项昂贵的操作,因为需要将项目转移到其位置之后。

答案 1 :(得分:2)

这确实是一个基本的洗牌。关键在于确保我们只有一个唯一的数字。

执行此shuffle循环迭代一次。

检查唯一性需要在循环中迭代一次...对于循环中的每个元素。

对于像这样的小循环,差异基本上是零,但一般来说,当给出两个选项时,你应该采用计算复杂度较低的那个......但总是记得注释代码以向未来的开发人员解释它!