Возможны некоторые оптимизации по алгоритму грубой силы.
Мы могли бы заставить алгоритм хранить по каждому индексу возможные суммы, рассчитанные из всех данных, которые следует справа. Эта информация будет заполнена во время отступления от рекурсии.
Пример: для упрощения рассмотрю только максимизацию суммы первой половины и минимизацию суммы второй половины.
[4, 1, 8, 2, 4, 1, 4]
алгоритм будет идти в глубину в сторону последнего элемента массива, а затем сохранить лучшую сумму там, только с учетом того, что следует справа. Поскольку ничего нет, сумма равна 4. Но поскольку мы хотим минимизировать, мы переключаем знак. Поэтому мы храним что-то вроде этого:
[4, 1, 8, 2, 4, 1, 4]
-4
Тогда мы возвращаемся. Там у нас есть две возможности: мы оставляем 1 as-is или используем среднее значение окружающих значений (т.4):
[4, 1, 8, 2, 4, 1, 4]
-4
-5
[4, 1, 8, 2, 4, 4, 4]
-4
-8
Оба значения -5 и -8 будут храниться в хэш, так что для значения 1 можно найти -5, и значение 4 можно найти -8.
В какой-то момент в алгоритме мы попробуем со значением 6 во втором элементе массива (вместо 1), а затем снова рекурсивно. Когда мы приходим к одному, но последнему элементу, мы обнаруживаем, что возможные значения снова 1 или 4 (если ничего не было изменено с левой стороны), и поэтому нам не нужно регрессировать глубже: мы можем прочитать суммы из хеша, которые мы поддерживаем при этом индексе.
Эта система может принести большую экономию в больших массивах, следя за тем, чтобы алгоритм только углублялся в рекурсию, когда это действительно необходимо. Очевидно, что это связано с затратами с точки зрения пространства.
Затем весь алгоритм может быть выполнен второй раз, но затем заменяется знаком. Из этих двух результатов достигается наилучшее решение, максимизирующее абсолютную величину.
Передавая значение измененного элемента в качестве аргумента функции, мы можем избежать создания нескольких массивов и просто работать с входным массивом. С другой стороны, хэш - созданный при каждом индексе - занимает некоторое пространство.
Вот алгоритм в JavaScript, в котором я не использовал никаких замысловатых ухищрений, поэтому она должна быть легко следовать:
function getMaxSum(a) {
// Index of the element in the middle. If integer,
// the element at this index will not play a role in any sum:
var mid = (a.length-1)/2;
// Two results, one that maximises the left sum and minimises the right sum
// The other minimises the left and maximises the right:
var result, result2, b;
function recurse(prevVal, index, sign, hash = []) {
var val, nextVal, sum, result, avg;
val = a[index];
if (index >= a.length-1) {
// At the last element there are no choices left:
return { sum: -sign*(prevVal+val), nextVal: val, hash: [] };
}
if (!hash[index]) hash[index] = [];
nextVal = a[index+1];
result = { sum: -Infinity, nextVal: 0, hash: hash[index] };
// Loop through the 2 possibilities (in general): take value as is, or
// take the average of previous and next value:
while (true) {
// If the result from this position onward is not know, calculate
// it via a recursive call:
if (!hash[index][val]) hash[index][val] = recurse(val, index+1, sign, hash);
// Add the previous value to the best sum at this point, using the appropriate sign,
// and store the result in a hash table, for future reference:
sum = hash[index][val].sum + (index-1 > mid ? -1 : index-1 < mid ? 1 : 0) * sign * prevVal;
if (sum > result.sum) {
result.sum = sum;
result.nextVal = val;
}
if (prevVal % 2 || nextVal % 2 || (avg = (prevVal + nextVal)/2) === val) break;
val = avg;
}
return result;
}
// Calculate both results
result = recurse(a[0], 1, 1, []);
result2 = recurse(a[0], 1, -1, []);
// Pick the best one.
if (Math.abs(result2.sum) > Math.abs(result.sum)) result = result2;
// Rebuild the array corresponding to the best result:
b = [a[0]];
while (result) {
b.push(result.nextVal);
result = result.hash[result.nextVal];
}
return b;
}
// Sample data
var a = [4, 1, 8, 2, 4, 1, 4];
console.log(' input: ' + a);
// Apply algorithm
var b = getMaxSum(a, 1);
// Print result
console.log('result: ' + b);
StackOverflow является ** не ** домашнее задание оказание услуг. Сколько раз это нужно сказать каждый день? :( – byxor
Кажется, это сложная проблема. Не могли бы вы предоставить источник проблемы. – Tempux
Был ли кто-либо из ответов в соответствии с вашими потребностями? Не могли бы вы принять его или оставить комментарий? – trincot