Позвольте B
быть списком парных сумм, с B[0] <= B[1] <= ... <= B[m-1]
, и пусть A
будет исходным списком чисел, которые мы пытаемся найти, с A[0] < A[1] < ... < A[n-1]
, где m = n(n-1)/2
.
С учетом A[0]
, вычислить A
за полиномиальное время
Построить A
от наименьшего элемента к наибольшему.Предположим, что мы уже знаем A[0]
.Тогда, поскольку B[0]
является наименьшим элементом в B
, он может возникнуть только как A[0] + A[1]
.Точно так же B[1]
должен равняться A[0] + A[2]
.Следовательно, если мы знаем A[0]
, мы можем вычислить A[1]
и A[2]
.
После этого, однако, этот шаблон ломается.B[2]
может быть A[0] + A[3]
или A[1] + A[2]
, и без предварительного знания мы не можем знать, какой это.Однако, если мы знаем A[0]
, мы можем вычислить A[1]
и A[2]
, как описано выше, а затем удалить A[1] + A[2]
из B
.Затем гарантируется, что следующим наименьшим элементом будет A[0] + A[3]
, что позволит нам найти A[3]
.Продолжая так, мы можем найти все A
без возврата.Алгоритм выглядит примерно так:
for i from 1 to n-1 {
// REMOVE SEEN SUMS FROM B
for j from 0 to i-2 {
remove A[j]+A[i-1] from B
}
// SOLVE FOR NEXT TERM
A[i] = B[0] - A[0]
}
return A
Вот как это работает на вашем примере, где B = [4,5,7,10,12,13]
, если мы знаем A[0]=1
:
start
B = [4,5,7,10,12,13]
A[0] = 1
i=1:
B = [4,5,7,10,12,13]
A[1] = 4-1 = 3
i=2:
Remove 1+3 from B
B = [5,7,10,12,13]
A[2] = 5-1 = 4
i=3:
Remove 1+4 and 3+4 from B
B = [10,12,13]
A[3] = 10-1 = 9
end
Remove 1+9 and 3+9 and 4+9 from B
B = []
A = [1,3,4,9]
Так что все сводится к знаниюA[0]
, из которого мы можем вычислить остаток A
.
Вычислить A[0]
за полиномиальное время
Теперь мы можем просто попробовать каждую возможность для A[0]
.Поскольку мы знаем B[0] = A[0] + A[1]
, мы знаем, что A[0]
должно быть целым числом от 0
до B[0]/2 - 1
.Мы также знаем, что
B[0] = A[0] + A[1]
B[1] = A[0] + A[2]
Более того, существует некоторый индекс i
с 2 <= i <= n-1
такой, что
B[i] = A[1] + A[2]
Почему?Потому что единственные записи, потенциально меньшие A[1]+A[2]
, имеют форму A[0] + A[j]
, и таких выражений может быть не более n-1
.Поэтому мы также знаем, что
A[0] = (B[0]+B[1] - B[i])/2
для некоторых 2 <= i <= n-1
.Это, вместе с тем, что A[0]
находится между 0
и B[0]/2-1
, дает только несколько возможностей для A[0]
для тестирования.
Например, есть две возможности для A[0]
:0
или 1
.Если мы попробуем алгоритм с A[0]=0
, вот что произойдет:
start
B = [4,5,7,10,12,13]
A[0] = 0
i=1:
B = [4,5,7,10,12,13]
A[1] = 4-0 = 4
i=2:
Remove 0+4 from B
B = [5,7,10,12,13]
A[2] = 5-0 = 5
i=3:
Remove 0+5 and 4+5 from B
B = !!! PROBLEM, THERE IS NO 9 IN B!
end