Прежде всего, обратите внимание, что это удобная рекурсивная проблема: всякий раз, когда вы объединяете смежные узлы, вы уменьшаете проблему на один узел. Состояние проблемы может быть полностью выражено в виде списка значений и максимального значения; Ваша заданная проблема может быть отправлена в функцию решения как
a = [-1, -5, 4, -2]
balance(a, max(max(a), abs(min(a))))
Проще говоря,
balance(a, 5)
Правое решение этой проблемы будет развиваться следующим образом:
[-1, -5, 4, -2], 5
[-1, -1, -2], 5 * see note below
[-1, -3], 5
[-4], 5
- отсюда, соединение не имеет значения, так как не осталось ни одного пути, который мог бы превысить первоначальное расхождение в 5.
Я предлагаю полугадовый подход : цель состоит в том, чтобы работать наружу от максимального узла и избежать его ухудшения или минимизировать ущерб. Найдите максимальный узел. Также суммируйте последовательность: нам не нужно тратить время, пытаясь избежать этой неизбежной суммы. Например, учитывая
-5 1 1 -5 1 1 -5 1
Нам не нужно кричать от идеи понижения ниже -5: итоговое значение равно -10, поэтому мы не можем избежать такого высокого расхождения. Это может быть более поздней тонкой настройкой
Для начала посмотрите на каждую сторону этого максимального узла; обрабатывать каждый как список, начинающийся рядом с этим узлом. Поиск подпоследовательности, сумма которой имеет противоположный знак; если он найден, сверните его (принимая эту последовательность как подзадачу), а затем объедините ее с проблемным узлом.
Например:
4 -5 1 1 2 -1 -1 -6 -2 -1 2 -3 2 2
расхождение составляет 6
около середины. Разделите последовательность в этой точке на две отступающие подпоследовательности с их текущими суммами:
seq: -1 -1 2 1 1 -5 4
sum: -1 -2 0 1 ...
seq: -2 -1 2 -3 2 2
sum: -3 -3 -1 -4 -2 0
Левая сторона (обратная, в порядке от элемента -6
) достигает контрбалансовой суммы ( противоположный знак, поэтому их объединение уменьшит расхождение) в четвертом элементе: -1 -1 2 1
- самая короткая подпоследовательность с положительной суммой. Повторите для [1 2 -1 -1], 6
как подзадачу (поддерево для рассмотрения). Это вернет поддерево, такое как ((1 (2 -1) )-1)
, со значением 1
. Теперь список значений:
4 -5 1 1 -6 -2 -1 2 -3 2 2
^ this is the sub-tree we just reduced.
Теперь у нас есть значение уравновешивания, смежное с наибольшим расхождением; это означает, что следующая операция состоит в объединении этих двух значений:
4 -5 1 -5 -2 -1 2 -3 2 2
Продолжайте аналогичным образом здесь. Обратите внимание, что свобода возврата к значению 6
может - в некоторых случаях - ускорить поиск решения.
Продолжая по частям, мы свернем это значение до
-1 -4 -2 -1 2 -3 2 2
Это будет прогрессировать справа, постепенно уменьшаясь ...
-1 -4 -2 -1 2 -3 2 2
-1 -4 -2 -1 2 -1 2
-1 -4 -2 1 -1 2
-1 -4 -1 -1 2
-1 -4 -1 1
-1 -4 0
Здесь мы окончательно выползли обратно к наибольшему оставшемуся значению в полном списке ...
-1 -4 0
-1 -4
-5
Этого достаточно, чтобы заставить вас двигаться?