【问题标题】:Efficiently: Random numbers in fixed range without repetitions高效:固定范围内的随机数,不重复
【发布时间】:2011-03-27 16:31:00
【问题描述】:

大家好,我知道有一百万个关于随机数的问题,但正是因为如此,我搜索了很多,但我找不到与我的类似的东西 - 没有暗示它不存在。无论如何,如果我重复一个问题,请原谅我,如果是这样的话,请指出我。

所以,我想以最有效的方式做一些简单的事情。

我想随机生成[0, N]范围内的所有N整数,一个接一个,这样就没有重复了。

我知道,我可以通过在 list 中插入所有内容、随机播放、获取头部然后从列表中删除头部来做到这一点。但随后我会将我的长度列表改组NN-1 次。

有更好/更快的想法吗?

【问题讨论】:

  • 从技术上讲(或者我猜是理想情况),随机播放一次就像随机播放 N-1 次一样,不是吗?
  • 什么语言?有些语言为此提供了 lib 函数。

标签: oop random performance


【解决方案1】:

您可以只进行一次随机播放,然后逐步浏览列表。

我推荐Fisher-Yates shuffle

【讨论】:

    【解决方案2】:

    这个问题已被问过几次,每次给出的正确答案都是随机排列一个数组(原始数组或索引数组),但是如果数字可能的索引非常大(要么是巨大的,要么是内存紧张,或者你只是出于某种原因渴望最大的效率)。

    因此,为了完整起见,我想添加一个替代方案。现在,这并不是真正随机的,所以如果这是您需要的,那么不要使用它,但是,如果您的目标只是“足够好”且内存要求最低,那么下面的伪代码可能感兴趣:

    function init:
        start = random [0, length)      // Pick a fully random starting index
        stride = random [1, length - 1) // Pick a random step size
        next_index = start
    
    function advance_next_index:
        next_index = (next_index + stride) % length
        if next_index is equal to start then
            start = (start + 1) % length
            next_index = start
    

    这是一个示例,说明如何实现一个可重用的函数来获取伪随机值:

    counter = length
    function pseudo_random:
        counter = counter + 1
        if counter is equal to length then
            init()
            counter = 0
        advance_next_index()
        return next_index
    

    很简单,pseudo_random 将在每个length 迭代中调用一次init,从而重新洗牌由advance_next_index 产生的结果的“随机”模式,并确保对于每个length 值没有单个重复。

    重申;这不是一个特别随机的算法,因此它不得用于需要真正随机性的情况。然而,对于一些基本的、非关键的任务,结果是足够随机的,而且它的内存占用很小。例如,如果您只想随机化游戏中的某些行为以避免重复,或者数据集很大并且从未暴露给用户(在这种情况下它实际上是随机的),这将需要很长时间拼凑订单并以某种方式利用它。

    如果有人知道任何具有相似属性的更好算法,请分享!

    【讨论】:

      猜你喜欢
      • 2017-02-13
      • 2018-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-23
      • 2014-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多