随机数数组优化

时间:2018-11-02 20:15:28

标签: javascript

我有一个生成随机数数组的函数。它可以工作,但是我认为对大数字它可能工作缓慢。有没有一种方法可以对其进行优化?

function renerateRandomNumbers(maxNumber, randomNumbersCount) {
    let i;
    const arrResult = [];
    for (i = 0; i < randomNumbersCount; i++) {
        let rand = Math.random() * (maxNumber);
        rand = Math.round(rand);
        if (arrResult.indexOf(rand) === -1 ) {
            arrResult.push(rand);
        } else {
            i--;
        }
    }
    return arrResult;
}

3 个答案:

答案 0 :(得分:2)

您的代码的问题在于,复杂度会以几何方式增长,因为它有机会生成已经被多次选择的数字。

我们需要实现的是在每次迭代中获取数字,以使迭代次数等于package.json

如何避免使用多个相同的随机数?

假设您要从 0-10 范围内的 5 个随机数

第一次迭代

  1. 使用值randomNumbersCount

  2. 创建一个数组
  3. 生成随机数,例如var candidates = [0,1...10]

  4. 在结果中存储数字0

  5. candidates[0]中删除0。为了对candidates数组进行有效索引,我们将candidates放入candidates[candidates.length - 1]并删除candidates[0]

  6. ,然后将执行此操作candidates[candidates.length - 1]次。

第二次迭代

  1. 我们的候选数组现在为randomNumbersCount

  2. 生成随机数,再说一次[10,1,2,3,4,5,6,7,8,9]。哇,我们生成了相似的随机数,但是那又如何呢?

  3. 我们的结果中包含0,但是0不再是candidates[0] 0现在是candidates[0]

  4. ,因此我们选择10的{​​{1}}并将其存储并将其从候选者中删除。将candidates[0]10)放入candidates[candidates.length - 1]并删除9

  5. 我们的结果现在是[0,10]

第三次迭代

  1. 我们的candidates[0]现在为candidates[candidates.length - 1]

  2. 生成随机数,例如candidates

  3. 我们不再担心,因为我们知道[9,1,2,3,4,5,6,7,8]0

  4. 添加candidates[0](女巫是9),我们正在保存结果,并将其从candidates[0]

  5. 中删除
  6. 我们的结果是9candidates[0,10,9]

以此类推

BTW的实现比解释要短得多:

candidates

答案 1 :(得分:2)

编辑-对于以后的任何用户,@ ScottSauyet的解决方案都应该是公认的答案。比我的解决方案更有效。

我认为解决此问题的算法最有效的方法是从0-maxNumber生成所有可能数字的列表,对数组(O(n)进行混洗,然后取第一个{{1} }改组数组中的数字。看起来如下:

randomNumbersCount

答案 2 :(得分:1)

通过mhodges的解决方案是相当有效的,但是仅当所寻求的计数非常接近最大值时才有效。如果您的数量少得多,则可能会出现问题,因为解决方案是O(m + n),其中m是最大值,而n是期​​望的数量。在太空中也O(m)。如果m大,则可能是个问题。

通过执行相同的操作,变体可以在时间和空间上达到大约O(n),但是当我们到达count项时并且不预先填充数组而是而是默认为其索引。

function venerateRandomNumbers(max, count) {
  // todo: error if count > max
  const arr = new Array(max + 1)
  for (let i = max; i > max - count; i--) {
    const j = Math.floor(Math.random() * (i + 1))
    const temp = arr[j] || j
    arr[j] = arr[i] || i
    arr[i] = temp
  }
  return arr.slice(-count)
}

console.log(venerateRandomNumbers(1000000, 10))

您可以在repl.it上查看性能比较