Изменения

Перейти к: навигация, поиск
Нет описания правки
__TOC__Дан массив из <tex>n</tex> чисел: <tex>a[0..n- 1]</tex>. Требуется найти в этой последовательности строго возрастающую подпоследовательность наибольшей длины.
{{Определение
|definition =
}}
== Решение за время O(N<sup>2</sup>) ==
Строим таблицу Построим массив <tex> a[0 \dots n - 1] d</tex>. Каждый её элемент , где <tex> ad[i] </tex> <tex> - </tex> это длина наибольшей возрастающей подпоследовательности, оканчивающейся точно в позиции элементе, с индексом <tex> i </tex>. Если мы построим эту таблицуМассив будем заполнять постепенно - сначала <tex>d[0]</tex>, то ответ к задаче - наибольшее число потом <tex>d[1]</tex> и т.д. Ответом на нашу задачу будет максимум из этой таблицывсех элементов массива <tex>d[]</tex>.Само построение тоже элементарноЗаполнение массива будет следующим: если <tex> ad[i] = \max{(1</tex>, то искомая последовательность состоит только из числа <tex>a[ji]</tex>. Если <tex>d[i] + > 1)} </tex>,для всех то перед числом <tex>a[i]</tex> в подпоследовательности стоит какое-то другое число. Переберем его: это может быть любой элемент <tex> a[j](j = 1\dots 0...i-1)</tex>, для которых но такой, что <tex> a[j] < xa[i] </tex>. База динамики Пусть на каком-то шаге нам надо посчитать очередное <tex> ad[i]</tex>. Все элементы массива <tex>d[]</tex> до него уже посчитаны. Значит наше <tex>d[i]</tex> мы можем посчитать следующим образом: <tex>d[i] = max(d[1j] </tex>, для всех <tex>j = 0...i - 1 )</tex> при условии, что <tex>a[j] < a[i]</tex>.Если Пока что мы хотим восстановить нашли лишь максимальную длину наибольшей возрастающей подпоследовательности, но саму подпоследовательность, то ее мы вывести не можем. Для восстановления ответа заведем массив предыдущих величин <tex>prev[0...n - 1]</tex> такой, что где <tex>prev[i]</tex> - предпоследний элемент будет означать индекс в НВПмассиве <tex>a[]</tex>, оканчивающейся в элементе с номером при котором достигалось наибольшее значение <tex> d[i ]</tex>. Его значение будет изменяться вместе Для вывода ответа будем идти от элемента с изменением соответствующего i-ого элемента матрицы максимальным значениям <tex>ad[i]</tex>по его предкам.===Псевдокод===
<code>
vector <int> Find(vector <int> a) { int n = a.size();//размер исходной последовательности vector<int > prev[maxN](n); vector<int> d(n);//массив предков for i = 0...n- 1 ad[i] = 1; prevp[i] = -1; for j = 0...i - 1 if(a[j] < a[i]) a if d[j] + 1 > d[i] = max(a d[i], 1 + a= d[j])+ 1; prev[i] = j; int ans length = d[0], pos = 0; //length - длина наибольшей подпоследовательности, pos - последний символ наибольшей возрастающей подпоследовательности for i = 0...n - 1 ans if d[i] > length length = max(ans, d[i]); pos = i; vector <int> answer; while(pos != -1) //восстанавливаем предка answer.push_back(a[pos]);
pos = prev[pos];
reverse(answer.begin(), answer.end()); return answer; }
</code>
 
== Решение за O(NlogN) ==
Для более быстрого решения данной задачи построим следующую динамику: пусть <tex>d[i](i = 0...n)</tex> - число, на которое оканчивается возрастающая последовательность длины <tex>i</tex>, а если таких чисел несколько - то наименьшее из них. Изначально мы предполагаем, что <tex>d[0] = -</tex><tex>\infty</tex>, а все остальные элементы <tex>d[i] =</tex> <tex>\infty</tex>.
Заметим два важных свойства этой динамики: <tex>d[i - 1] <= d[i]</tex>, для всех <tex>i = 1...n</tex>. А так же что каждый элемент <tex>a[i]</tex> обновляет максимум один элемент <tex>d[j]</tex>. Это означает, что при обработке очередного <tex>a[i]</tex>, мы можем за <tex> O(n\cdot\log n) </tex> c помощью двоичного поиска в массиве <tex>d[]</tex> найти первое число, которое строго больше текущего <tex>a[i]</tex> и обновить его.
Для восстановления ответа будем поддерживать заполнение двух массивов:<tex>pos</tex> и <tex>prev</tex>. В <tex>pos[i]</tex> будем хранить позицию <tex>d[i]</tex> в <tex>a[i]</tex>, а в <tex>prev[i]</tex> - позицию предыдущего элемента для <tex>a[i]</tex>.
===Псевдокод===
<code>
vector <int> Find(vector <int> a)
10
правок

Навигация