Динамическое программирование. Задача о возрастающей подпоследовательности наибольшей длины.
Условие
Задача о возрастающей подпоследовательности наибольшей длины: Дана последовательность чисел, необходимо найти наибольшую по длине возрастающую подпоследовательность.
Для последовательности {1, 4, 2, 5, 3} решение будет таким:
- f5 = 1 + max(f1, f3)
- f4 = 1 + max(f1, f2, f3)
- f3 = 1 + max(f1)
- f2 = 1 + max(f1)
- f1 = 1. Возвращаемся назад
- f2 = 1 + max(f1) = 2
- f3 = 1 + max(f1) = 2
- f4 = 1 + max(f1, f2, f3) = 3
- f5 = 1 + max(f1, f3) = 3. Решение есть max(f1, f2, f3, f4, f5) = 3.
Чтобы повторно не решать решённые подзадачи, введём массив c размером, хранящий значения вычисленных функций. Начальные значения его равны нулю — значению, которое не может быть верным решением любой из одзадач. Это позволит нам определить, решали ли мы эту подзадачу или нет. Если нет — запускаем решение для требуемого аргумента, и после получения результата сохраняем его.
Решение
Алгоритм сложностью O(n^2):
есть входной массив последовательности a[....], и массив dp[...], где будем хранить максимальное значение длины последовательности, так что dp[ i ] - это максимальная длина последовательности которая оканчивается на a[i].
Начальное значение dp[o] = 1.
Порядок действий для нахождение dp[i]:
- получаем значение из a[ i ]
- циклом проходимся по элементам начиная с i до 0
- если находим значение a[ j ] меньшее нашего, получаем длину его подпоследовательности как dp[ j ]
- в dp[ i ] заносим максимальное из найденных значений в п.3 с “+ 1”
Алгоритм сложность O(n log n):
- создадим дополнительный массив dp длины N (длина входного массива a): нулевой элемент ставим -INF, остальные INF ( dp = [-inf, inf, inf, …].)
- получаем dp[ i ], i - длина последовательности, dp[ i ] - значение последнего элемента этой последовательности
- благодаря такой структуре все значения в dp будут хранится в отсортированном порядке, ведь чем больше значение, тем больше элементов могут поместиться перед ним 4) проходимся по a[] и бинарным поиском находим такое k, что (dp[k-1] < x && dp[k] >= x) и присваиваем dp[k] значение x
- ответ, это наибольший индекс массива dp отличный от INF