假设N = 3,我想制作一个函数来生成3个唯一的随机数,如果所有数字加起来等于3。例如:
List
我已经在下面的JavaScript中拥有了自己的解决方案:
numbers = [1, 0, 2]
numbers = [2, -4, 5]
但是我对最后一个索引仍然有疑问,该索引往往会出现很大的偏差。例如,对于N = 10,我可能会得到如下所示的结果:
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;
}
}
我想知道你们是否拥有更好的解决方案以及更好的性能。谢谢!
答案 0 :(得分:1)
编辑后:(我对此进行了更多思考,并认为我找到了更好的方法,如下所述)
这就是我想出的。这使列表显得更加随机,虽然可能有一些元素比其他元素偏离更多,但确实有可能来自任何索引的元素。它只需要一个小的变化。
您有:
let randomNumber = getRandomInt(number);
替换为:
let randomNumber = getRandomInt(number) + i - currentSum;
其中currentSum
只是数组的滚动总和,i
是一个递增变量,从零开始,每经过一次递增一次,这两个变量都将在while循环。 (换句话说,这将替换您拥有的summed
变量,因为当数组生成随机数时,它将跟踪总和)。此更改旨在做的是对随机数进行归一化,以使总和与假定所围绕的滚动没有太大关系。为了对 n 个数字求和并添加到 n 中,“平凡”的解决方案是使每个数字都为1(即,滚动总和只是数组的索引)。上面的代码更改所做的是创建一个随机数,该随机数围绕我刚刚描述的预期滚动总和生成随机数。因此,如果我要运行一百万次代码,则数组中每个值的平均值将为1,这对于想要您所描述的列表来说是完美的。我在Java中真正快速地测试了此方法,它似乎可以满足您的要求,因此希望这种“快速修复”方法能有所帮助。
进一步减少偏差的另一种想法(尽管我没有对此进行测试)是,除了上述更改外,还使generateRandomInt()
函数在较小的范围内生成数字,因为此函数现在会生成范围为2 * number
的数字,可能会产生比您想要的数字更大的数字。
以下是我运行更改后的代码(使用number = 10
)时得到的一些测试数组:
[-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]
希望您对此有所了解;希望这会有所帮助!
P.S。我相信您发布的代码应在else块内包含i++
命令,否则您可能无法填满整个数组。
答案 1 :(得分:1)
这是一个片段,该片段首先在-N到N之间的范围内用N个唯一数字填充数组。
然后替换数组中的最后一个值,以使总数= N。
当重新计算的最终值已包含在数组中时,该函数将递归。
为避免最后一个值不是唯一的。
并且当最终值偏离很大时也会重复发生。
UCHAR_MAX = 255
(unsigned char)-1 = 255
-1 with %hhu conversion: 255