Я работал над чем-то похожим, и вот что я придумал.
Вы можете сделать это в O (N-1) , используя некоторые вычисления на каждом шаге. Вы начинаете с выбора случайного числа между минимальным и максимальным числом для каждого места. Для каждого пятна максимальное число рассчитывается путем вычитания (Min_Number * Remaining_Spots) из Остаточного баланса.
Например: для первого места вы выбираете число от 2 до 38. Вы получаете это, вычитая (7-1) * 2 из 50. То есть 50 - 12 = 38.
Как только вы выберете число, скажем, 19, то для следующего места диапазон будет 2-21. то есть 50-19- (5 * 2) = 21 ..
.. и т. Д.
Вот фрагмент кода:
function splitNumIntoXRandomComponents(num, x, min_num) {
var components = [];
var count = 1;
var cumulative = 0;
var balance = num;
for (var i = 0; i<x-1; i++) {
//max num for this spot
var max_num = balance - ((x-count)*min_num);
//to avoid big numbers in the beginning and min numbers at the end
if (Math.random() > 0.5){ //0.5 can be tuned to your liking
max_num = Math.floor(max_num / 2) + min_num;
}
//generate the number for the spot at 'count'
var c = Math.floor(Math.random()*(max_num-min_num+1)+min_num);
//adjust balances
cumulative += c;
balance -= c;
count++;
//store this number
components.push(c);
}
//push remaining balance into the last spot
components.push(balance);
//print numbers
console.log(components);
}
for (var i=0; i<10; i++) {
splitNumIntoXRandomComponents(50, 7, 2);
}
Вот пример вывода:
[34, 2, 4, 3, 3, 2, 2]
[14, 12, 8, 8, 4, 2, 2]
[7, 4, 26, 5, 2, 3, 3]
[8, 2, 16, 4, 4, 9, 7]
[20, 8, 4, 4, 7, 4, 3]
[3, 34, 4, 2, 2, 2, 3]
[10, 5, 15, 2, 7, 5, 6]
[6, 3, 10, 4, 10, 3, 14]
[31, 4, 2, 3, 5, 2, 3]
[7, 5, 2, 9, 9, 2, 16]
Вот jsFiddle:
http://jsfiddle.net/wj81kvsc/6/