Примечание о методологии
Я немного подумал об этой проблеме и пришел к решению. Когда я прочитал ответ Саида Амири , я понял, что я разработал специализированную версию стандартного алгоритма поиска самой длинной подпоследовательности для последовательности длины 3. Я публикую сообщение о том, как я нашел решение, потому что я думаю, что оно интересный пример решения проблем.
Двухэлементная версия
i<jA[i]<A[j]
A∀i<j,A[i]≥A[j]∀i,A[i]≥A[i+1]iA[i]<A[i+1]
Этот случай очень прост; мы постараемся обобщить это. Это показывает, что заявленная проблема не решаема: запрошенные индексы не всегда существуют. Поэтому мы скорее спросим, что алгоритм либо возвращает действительные индексы, если они существуют, либо правильно утверждает, что таких индексов не существует.
Подойдя к алгоритму
A(A[i1],…,A[im])i1<⋯<imA(A[i],A[i+1],…,A[i+m−1])
Мы только что увидели, что запрошенные индексы не всегда существуют. Наша стратегия состоит в том, чтобы учиться, когда индексы не существуют. Мы сделаем это, предположив, что мы пытаемся найти индексы и увидим, как наш поиск может пойти не так. Тогда случаи, когда поиск не идет не так, предоставят алгоритм для поиска индексов.
j=i+1k=j+1A[i]<A[i+1]<A[i+2]
A[j]<A[j+1]iA[i]<A[j]kA[j+1]<A[k]
ik
ijki
i(i,j)ki(i,j)(i,j)i′>jA[i′]<A[i]i′i(i,j)j′A[j′]<A[j](i′,j′)
Постановка алгоритма
Приведено в синтаксисе Python, но учтите, что я его не проверял.
def subsequence3(A):
"""Return the indices of a subsequence of length 3, or None if there is none."""
index1 = None; value1 = None
index2 = None; value2 = None
for i in range(0,len(A)):
if index1 == None or A[i] < value1:
index1 = i; value1 = A[i]
else if A[i] == value1: pass
else if index2 == None:
index2 = (index1, i); value2 = (value1, A[i])
else if A[i] < value2[1]:
index2[1] = i; value2[1] = A[i]
else if A[i] > value2[1]:
return (index2[0], index2[1], i)
return None
Эскиз доказательства
index1
является индексом минимума части массива, которая уже была пройдена (если это происходит несколько раз, мы сохраняем первое вхождение) или None
перед обработкой первого элемента. index2
хранит индексы возрастающей подпоследовательности длины 2 в уже пройденной части массива, который имеет наименьший наибольший элемент, или, None
если такая последовательность не существует.
Когда return (index2[0], index2[1], i)
работает, мы имеем value2[0] < value[1]
(это инвариант value2
) и value[1] < A[i]
(очевидно из контекста). Если цикл заканчивается без вызова досрочного возврата, то value1 == None
в этом случае нет увеличивающейся подпоследовательности длины 2, не говоря уже о 3, или value1
содержит возрастающую подпоследовательность длины 2, которая имеет самый низкий самый большой элемент. В последнем случае, кроме того, у нас есть инвариант, что никакая возрастающая подпоследовательность длины 3 не заканчивается раньше, чем value1
; следовательно, последний элемент любой такой подпоследовательности, добавленный к value2
, будет формировать возрастающую подпоследовательность длины 3: поскольку у нас также есть инвариант, который value2
не является частью увеличивающейся подпоследовательности длины 3, содержащейся в уже пройденной части массива, нет такой подпоследовательности во всем массиве.
Доказательство вышеупомянутых инвариантов оставлено в качестве упражнения для читателя.
сложность
O(1)O(1)O(n)
Формальное доказательство
Оставлено в качестве упражнения для читателя.