Пусть left(k)
представляют собой сумму значений в массиве, от A[0]
до A[k]
. Это тривиально, чтобы доказать, что:
left(k+1)=left(k)+A[k+1]
Что, если вы уже вычислен ваш left
для данного k
, то left
для k+1
вычисляется путем добавления следующего элемента в left
.
Другими словами:
Если перебрать массив из элемента # 0 в элемент # п-1 (где n
является размер массива), можно вычислить нарастающим итогом для left
просто добавление следующего элемента в массив к left
.
Это может показаться очевидным и само собой разумеющимся, но это помогает сформулировать это формально, чтобы следующий шаг в процессе стал одинаково очевидным.
Таким же образом, не учитывая right(k)
, представляющий собой сумму значений в массиве, начиная с элемента #k, до последнего элемента в массиве, можно также доказать следующее:
right(k+1)=right(k)-A[k]
Итак, вы можете найти k
с минимальной разницей между left(k)
и right(k+1)
(я использую несколько отличную нотацию, чем ваш вопрос, потому что мои записи более удобны), начиная с суммы всех значений в массиве как right(0)
и A[0]
как left(0)
, затем вычисляет right(1)
, то, про перейдя с самого начала на массив до конца, вычисляя как left
, так и right
на каждом шаге «на лету» и вычисляя разницу между левыми и правыми значениями. Найти, где разница является минимальным, становится тривиальным.
Я не могу думать о каком-либо другом способе сделать это, менее чем O(n)
:
1) Вычисление суммы всех значений в массиве, для начального значения right(0)
представляют собой О (п) ,
2) Итерация справа - это, конечно, O (n).
Я не верю, что здесь будет работать логарифмический бинарный поиск, поскольку сами значения не будут отсортированы в порядке сортировки.
Кстати, при таком подходе вы также можете найти минимальную разницу, когда массив содержит отрицательные значения. Единственное различие заключается в том, что, поскольку разница больше не является параболической, вам просто нужно перебирать весь массив и просто отслеживать, где abs(left-right)
является самым маленьким.
Похоже, что самый простой (и, возможно, оптимальный) метод - это линейный поиск, так что не нужно многократно пересчитывать большие суммы. Один линейный проход вычисляет общую сумму, которую вы инициализируете справа (слева инициализируется до 0), затем со вторым линейным проходом вы добавляете A [i] влево и вычитаете его справа, пока abs (влево-вправо) не начнет увеличиваться , Почему вы думаете, что тройной поиск будет лучше, чем этот простой метод? –
Тернарный поиск имеет смысл только в том случае, если у вас есть набор значений Sn-1, представляющий значения | Li - Ri | некоторого множества An. То есть, если у вас есть S уже. –
Алгоритм находится по адресу https://en.wikipedia.org/wiki/Ternary_search –