迭代随机置换的算法

时间:2016-12-13 12:29:24

标签: algorithm random permutation

我有一个包含以下内容的包:

  • 6红色大理石
  • 5个绿色大理石
  • 2蓝色大理石

我想从包中取出一块随意的大理石,记录下它的颜色,然后重复,直到包里不再留下大理石:

  1. 对计数进行排序
    • bag = {2:blue,5:green,6:red}
  2. 计算累积计数
    • 累积= {2:蓝色,7:绿色,13:红色}
  3. 在[0,最大累积计数]中选择一个随机数
    • rand(0,13)= 3
  4. 使用二进制搜索查找此整数的插入点索引
    • i = 1
  5. 记录与此索引对应的颜色
    • 绿色
  6. 将该计数减少1
    • bag = {2:blue,4:green,6:red}
  7. 重复,直到包里没有弹珠
  8. 这是一个很好的方法吗?或者在时间复杂度方面有更有效的方法吗?

2 个答案:

答案 0 :(得分:1)

您的算法非常好,但可以进一步优化:

  1. 您不需要对颜色进行排序!您可以跳过第一步。

  2. 不是每次都可以通过减少所选值(包括所选颜色本身)的所有值来迭代计算累积计数。

  3. 您也不需要二元搜索,您可以从最后开始减少累积计数,直至达到正确的数字。

  4. 还有另一种基于列表的算法:

    1. 创建一个包含所有项目的列表(0 =红色,1 =绿色,2 =蓝色):[0,0,0,0,0,0,1,1,1,1,1, 2,2]。

    2. 获取0和列表大小之间的随机整数i。

    3. 从列表中删除第i项并将其添加到结果中。

    4. 重复2.和3.直到列表为空。

答案 1 :(得分:1)

不是依赖于提取,而是可以就地对阵列进行随机播放。

  1. 就像在maraca的回答中一样,你将这些项目单独存储在数组中(在此引用它:"创建一个包含所有项目的列表(0 =红色,1 =绿色,2 =蓝色):[0,0,0,0,0,0,1,1,1,1,1,2,2]。")

  2. 遍历数组,并为每个元素i选择一个元素的随机索引j以与

    交换位置
  3. 最后,只是遍历数组以获得一个洗牌顺序。

  4. 这样的东西
    for(i=0..len-1) {
      j=random(0..len-1);
      // swap them
      aux=a[i]; a[i]=a[j]; a[j]=aux;
    }
    // now consume the array - it is as random as it can be
    // without extracting from it on the way
    

    注意:许多编程语言都有提供已实现的数组/列表重排函数的库