import bisect
def lis(xs):
ret = []
for x in xs:
i = bisect.bisect_left(ret, x)
ret[i:i+1] = x,
return len(ret)
Пример:
>>> lis([10, 1, 2, 3])
3
>>> lis([10,22,9,33,21,50,41,60,80])
6
ПРИМЕЧАНИЕ В приведенном выше коде, ret
не содержит действительный подпоследовательности. Но длина правильная. Используйте приведенный выше код, что вы хотите, это только длина LIS.
Объяснение:
Подумайте о [10,22,9,11]
. Могут быть два LIS: [10,22]
, [9,11]
. ret
в приведенной выше функции lis
поддерживает следующее условие:
ret
сортируется; может использовать двоичный поиск (bisect.bisect_left)
ret[i]
содержит минимальное последнее значение для длины - i
подпоследовательность.
ret
изменяется ... (учитывая [10,22,9,11]
в качестве входных данных)
- [10] - после обработки 1-й элемент
- [10, 22] - после обработки 2-го элемента
- [9, 22] - ... Теперь минимальное значение для 1-подпоследовательности равно 9! 10 перезаписывается.
- [9, 11]
Сложность Время: О (пк) где п есть число элемента списка, к длина ЛИС.
UPDATE
Модифицированная версия, что правильно получить подпоследовательности:
import bisect
def lis(xs):
if not xs: return []
prev = {}
ret = []
for x in xs:
i = bisect.bisect_left(ret, x)
ret[i:i+1] = x,
prev[x] = ret[i-1] if i > 0 else None
subseq = [ret[-1]]
while subseq[-1] is not None:
subseq.append(prev[subseq[-1]])
return list(reversed(subseq[:-1]))
Пример:
>>> lis([])
[]
>>> lis([10, 1, 2, 3])
[1, 2, 3]
>>> lis([10,22,9,33,21,50,41,60,80])
[10, 22, 33, 41, 60, 80]
>>> lis([1,5,2,6,3,4])
[1, 2, 3, 4]
>>> lis([100,200,1,2,3])
[1, 2, 3]
[Википедия] (http://en.wikipedia.org/wiki/Longest_increasing_subsequence) содержит статью о проблеме, включая эффективность для его решения. Однако может быть трудно понять объяснение. – user2357112