Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   массив, распределение суммы как можно более равномерно (https://javascript.ru/forum/misc/74080-massiv-raspredelenie-summy-kak-mozhno-bolee-ravnomerno.html)

Alexandroppolus 12.06.2018 04:52

Цитата:

Сообщение от рони
если есть замечания напишите

Можно немного уменьшить объём вспомогательной памяти, если создать отсортированную копию интпута, по ней за один обход вычислить максимум, за второй обход уже расставить значения. Тогда, вроде бы, и арифметика вся будет целочисленной, без делений и округлений

Белый шум 12.06.2018 06:45

Alexandroppolus,
Максимум можно получить с помощью Math.max(), но чем это поможет - что-то не вдупляю.

рони,
Проход хоть и один, но для каждого элемента массива выполняется деление - сложная операция, по идее. Хотя я хз как там процессоры внутри работают, может им это и проще чем пару лишних проходов сделать.

рони 12.06.2018 08:33

Alexandroppolus,

Цитата:

Сообщение от Alexandroppolus
если создать отсортированную копию интпута

есть sortedOrder

Цитата:

Сообщение от Alexandroppolus
вычислить максимум

max = sortedOrder.slice(-1)[0].value
и как это использовать?

Alexandroppolus 18.06.2018 13:02

рони,
я про тот "максимум", который можно отсыпать в output[i]

вот, изобразил слова в г-коде. Идея в принципе та же, но нет деления на каждой итерации (есть только целочисленное умножение), и дополнительной памяти только массив целых чисел, а не массив объектов. Не знаю, насколько это сможет ускорить, проверять было лень :)

function allocate(input, total) {
    var output = [];
    var length = input.length;
    var sortedInput = input.slice().sort(function (a, b) { return a - b; });
    var lastValue = 0;
    var maxH = 0;
    var remainder = 0;

    for (var i = 0; total > 0 && i < length; ++i) {
        var item = sortedInput[i];
        var height = item - lastValue;
        if (height > 0) {
            lastValue = item;
            var width = length - i;
            var area = width * height;
            if (total < area) {
                height = Math.floor(total / width);
                remainder = total % width;
            }
            maxH += height;
            total -= area;
        }
    }
    for (var i = 0; i < length; ++i) {
        var item = input[i];
        output.push(item > maxH ? maxH + (--remainder >= 0 ? 1 : 0) : item);
    }
    return output
}

// проверка для разных total
var input = [5,10,0,12, 7, 3];
for (var total = 0; total < 41; total++) {
    var output = allocate(input, total);
    console.log(`${total} => ${output}`);
}


см. консоль

рони 18.06.2018 15:21

Alexandroppolus,
:thanks:


Часовой пояс GMT +3, время: 08:08.