Javascript 生成一个唯一的N个随机数数组,如果所有数的总和等于N

Javascript 生成一个唯一的N个随机数数组,如果所有数的总和等于N,javascript,arrays,random,Javascript,Arrays,Random,假设N=3,我想做一个函数来生成3个唯一的随机数,如果所有的数加起来等于3。例如: numbers = [1, 0, 2] numbers = [2, -4, 5] 我已经有了自己的JavaScript解决方案,如下所示: let i = 0; let arr = [] function getRandomInt(number) { return Math.floor(Math.random()*(number*2)) - number; } function generateArra

假设N=3,我想做一个函数来生成3个唯一的随机数,如果所有的数加起来等于3。例如:

numbers = [1, 0, 2]
numbers = [2, -4, 5]
我已经有了自己的JavaScript解决方案,如下所示:

let i = 0;
let arr = []

function getRandomInt(number) {
  return Math.floor(Math.random()*(number*2)) - number;
}

function generateArray(i, arr, number) {
  let lastIndex = number-1;

  while (i < lastIndex) {
    let randomNumber = getRandomInt(number);
    if (arr.indexOf(randomNumber) > -1) {
      continue;
    } else {
      arr[i] = randomNumber;
    }
    i++;
  }

  let summed = arr.reduce((a, b) => a+b);
  let lastNumber = number - summed;
  if (arr.indexOf(lastNumber) > -1) {
    return generateArray(lastIndex-1, arr, number);
  } else {
    arr[lastIndex] = lastNumber;
    return arr;
  }
}
我想知道你们是否有一个性能更好的解决方案。谢谢大家!

编辑:(我对此思考了更多,并认为我找到了更好的方法,如下所述)

这是我想到的。这使得列表看起来更随机,虽然可能有一些元素的偏差比其他元素更大,但这样做的元素可能来自任何索引。它只需要一点零钱

你有:

let randomNumber = getRandomInt(number);
将其替换为:

let randomNumber = getRandomInt(number) + i - currentSum;
其中,
currentSum
只是数组的滚动和,
i
是一个递增变量,从零开始,每次通过递增一个,这两个变量都将在while循环的else块中更新。(换句话说,这将替换现有的
summated
变量,因为这将在数组生成随机数时跟踪总和)。这一变化的目的是规范化随机数,使其总和不偏离滚动数的范围。要将n个数字相加到n中,“普通”解决方案是使每个数字都为1(即滚动和只是数组的索引)。上面的代码更改所做的是创建一个随机数,该随机数围绕我刚才描述的预期滚动和生成随机数。因此,如果我将代码运行一百万次,数组中每个值的平均值都将是1,这对于您所描述的列表来说是完美的。我用Java real quick测试了这个方法,它似乎可以满足您的需要,所以我希望这个“快速修复”能有所帮助

另一个进一步减少偏差的想法(我没有测试这个)是,除了上面的更改之外,让
generateRandomInt()
函数以较小的范围生成数字,因为现在这个函数生成的数字的范围是
2*number
,这可能会产生比你想要的更大的数字

下面是我在运行更改后的代码时得到的一些测试数组(使用
number=10
):

我希望你明白这一点;希望这有帮助


另外,我认为您发布的代码应该在else块中包含
I++
命令,否则您可能无法填充整个数组。

下面是一个片段,它首先用-N到N之间的N个唯一数字填充数组

然后替换数组中的最后一个值,使总数=N

当重新计算的最终值已经是数组的一部分时,函数将递归。
以避免最后一个值不是唯一的。
当最终值偏离太大时,它也会再次出现

函数getArrayRandomNumbersInRange(最小、最大、N){ 设arr=[]; while(arr.length-1)继续; arr[arr.length]=num; } 设total=arr.reduce(函数(acum,val){return acum+val}); 设lastElem=arr[arr.length-1]-总计+N; 如果(lastElemmax | | |(总计!==N&&arr.indexOf(lastElem)>-1)){ //log(lastElem+'->recurse'); arr=[]; 返回getArrayRandomNumbersInRange(最小、最大、N); } arr[arr.length-1]=lastElem; 返回arr; } 函数getArrayRandomNumbers(N){ 返回getArrayRandomNumbersInRange(-N,N,N); } 函数数组(arr){ 返回arr.reduce(函数(acum,val){return acum+val}) } 设randomUniqueArray=getArrayRandomNumbers(5); log(“Total:\t”+sumArray(randomUniqueArray));
console.log(随机唯一数组)此问题不属于堆栈溢出问题。它应该在@ScottMarcus上,我认为这是一个很好的问题-codereview不接受需要调试的代码(比如这个),OP听起来像是在为这个问题要求一个全新的(更好的)算法,这听起来对codereview来说也太宽泛了。@CertainPerformance实际上,出于您所列举的所有原因,它绝对属于代码审查。这个问题太宽泛了,所以没有问任何具体的问题。这个问题很好。我不支持更多的结束投票。只是为了澄清Insan,你是说当N=10时,数组的所有值加起来应该是10吗?
let randomNumber = getRandomInt(number) + i - currentSum;
[-3, 10, 0, -4, -1, 6, -5, 5, -7, 9]
[-6, -2, 4, 6, -8, 8, 3, -4, 7, 2]
[-2, 4, -10, 1, 6, 13, -3, -6, 12, -5]