Стратегия
Следующий алгоритм линейного времени принимает стратегию зависания около , выбирая положительные или отрицательные числа на основе знака частичной суммы. Он предварительно обрабатывает список номеров; он вычисляет перестановку входных данных на лету при выполнении сложения.0
Алгоритм
- Partition 1 , ... , п в двух списках, положительные элементы P и отрицательные элементы M . Нули можно отфильтровать.a1, ... ,NпM
- Пусть .Su m = 0
- Хотя оба списка не пусты
- Если { S u m : = S u m + головка ( M ) ; М : = хвост ( М ) ; }Sты м > 0Su m : = Sты м + голова ( М)M: = хвост ( М)
- иначе { ; P : = хвост ( P ) ; }Su m : = Sты м + голова ( P)п: = хвост ( P)
- Когда один из двух списков станет пустым, добавьте остальную часть оставшегося списка на .S
Корректность
Корректность может быть установлена с помощью прямого индуктивного аргумента длины списка чисел.
Прежде всего, докажите, что если все положительные (или все отрицательные) и их сумма не вызывает переполнения, то и суммы префиксов не делайте. Это просто.a1, ... ,N
Во-вторых, доказать, что находится в пределах границ, является инвариантом цикла алгоритма. Понятно, что это верно при входе в цикл, так как S u m = 0 . Теперь, если S u m > 0 , добавление отрицательного числа, которое находится в пределах границ к S u m , не приводит к тому, что S u m выходит за пределы. Аналогично, когда S u m ≤ 0, добавление к сумме положительного числа, которое находится в пределах границ, не приводит к выходу S u m за пределы. Таким образом, выходя из цикла,Sты мSu m = 0Sты м > 0Sты мSты мSи м ≤ 0Sты м находитсяпределах границ.Sты м
Теперь можно применить первый результат, и их вместе достаточно, чтобы доказать, что сумма никогда не выходит за пределы.