Я нашел алгоритм для этого следующим образом:
- По заданному списку l вычислить его сумму s.
- Рассчитать следующую таблицу:
(s, Acc)
- (с, 0)
- (s-x1, x1)
(s-x1-x2, x1 + x2)
...
п. (S-x1 -... x_n-1, x1 + x2 + ... + x_n-1)
в то время как на каждом шаге вы проверяете, равен ли левый элемент пары второму.
Затем этот алгоритм определяет за линейное время, можно ли разбить ваш список на два подсписка, чтобы каждый подсписок суммировал одинаковую величину.
Я некоторое время пытался доказать это формально. Однако я начинаю думать, что это может быть допустимо только для натуральных чисел, а не для целых чисел.
- Можете ли вы подтвердить это мнение?
- Можете ли вы дать алгоритм для этого для целых чисел и для линейной сложности?
Редактировать (мое решение до сих пор)
fun check_list :: "int list ⇒ int ⇒ int ⇒ bool" where
"check_list [] n acc = False" |
"check_list (x#xs) n acc = (if n = acc then True else (check_list xs (n-x) (acc+x)))"
fun linear_split :: "int list ⇒ bool" where
"linear_split [] = False" |
"linear_split [x] = False" |
"linear_split (x # xs) = check_list xs (sum_list xs) x"