Подпоследовательность - это последовательность, которая может быть получена из другой последовательности путем удаления некоторых элементов без изменения порядка оставшихся элементов. Строго возрастающая подпоследовательность - это подпоследовательность, в которой каждый элемент больше предыдущего.
Самая тяжелая возрастающая подпоследовательность последовательности - строго возрастающая подпоследовательность, которая имеет наибольшую сумму элементов.
Реализуйте программу или функцию на выбранном вами языке, которая найдет сумму элементов самой тяжелой возрастающей подпоследовательности данного списка неотрицательных целых чисел.
Примеры:
[] -> 0 ([])
[3] -> 3 ([3])
[3, 2, 1] -> 3 ([3])
[3, 2, 5, 6] -> 14 ([3, 5, 6])
[9, 3, 2, 1, 4] -> 9 ([9])
[3, 4, 1, 4, 1] -> 7 ([3, 4])
[9, 1, 2, 3, 4] -> 10 ([1, 2, 3, 4])
[1, 2, 4, 3, 4] -> 10 ([1, 2, 3, 4])
[9, 1, 2, 3, 4, 5, 10] -> 25 ([1, 2, 3, 4, 5, 10])
[3, 2, 1, 2, 3] -> 6 ([1, 2, 3])
Обратите внимание, что вам нужно дать только сумму элементов самой тяжелой возрастающей подпоследовательности, а не саму подпоследовательность.
Асимптотически быстрый код выигрывает, с меньшим размером кода в байтах в качестве тай-брейка.
Ответы:
JavaScript (ES6)
O(n log n)
253 символапри этом используются деревья Фенвика (максимальное дерево Фенвика), чтобы найти максимумы определенных подпоследовательностей.
в основном, в базовом массиве типа данных каждое место сопоставляется с элементом из входного списка в том же порядке. дерево Фенвика везде инициализируется 0.
от самого маленького до самого большого, мы берем элемент из списка ввода и ищем максимум элементов слева. они являются элементами, которые могут находиться перед этим в подпоследовательности, потому что они находятся слева во входной последовательности и меньше, потому что они вошли в дерево ранее.
таким образом, максимум, который мы нашли, является самой тяжелой последовательностью, которая может попасть в этот элемент, и поэтому мы добавляем к этому вес этого элемента и устанавливаем его в дереве.
тогда мы просто возвращаем максимум всего дерева - это результат.
проверено на firefox
источник
Python, O (n log n)
Я не играл в гольф, потому что я соревнуюсь в первую очередь на самой быстрой стороне кода. Мое решение - это
heaviest_subseq
функция, и в нижней части также имеется тестовый жгут.Анализ времени выполнения:
Каждый элемент имеет свою позицию вставки, которая ищется один раз, вставляется один раз и, возможно, удаляется один раз, в дополнение к постоянному количеству поисков значений в цикле. Поскольку я использую встроенный пакет bisect и пакет blist , каждая из этих операций
O(log n)
. Таким образом, общее время выполненияO(n log n)
.Программа работает, поддерживая отсортированный список наилучших возможных увеличивающихся подпоследовательностей, представленный как кортеж конечного значения и суммы последовательности. Увеличивающаяся подпоследовательность находится в этом списке, если не найдено никаких других подпоследовательностей, конечное значение которых меньше, а сумма, по крайней мере, такая же большая. Они поддерживаются в порядке возрастания конечного значения и обязательно также в порядке возрастания суммы. Это свойство поддерживается путем проверки преемника каждой вновь найденной подпоследовательности и удаления его, если его сумма недостаточно велика, и повторения до тех пор, пока не будет достигнута подпоследовательность с большей суммой или достигнут конец списка.
источник
Python, O (n log n)
Я использовал преобразование индекса и изящную структуру данных (двоичное индексированное дерево), чтобы тривиализировать проблему.
Двоичное индексированное дерево может выполнять две операции в log (n): увеличивать значение по индексу i и получать максимальное значение в [0, i). Мы инициализируем каждое значение в дереве равным 0. Мы индексируем дерево, используя ранг элементов, а не их индекс. Это означает, что если мы индексируем дерево по индексу i, все элементы [0, i) будут элементами меньше, чем элемент с рангом i. Это означает, что мы получаем максимум из [0, i), добавляем к нему текущее значение и обновляем его в i. Единственная проблема заключается в том, что это будет включать значения, которые меньше текущего значения, но идут позже в последовательности. Но поскольку мы перемещаемся по последовательности слева направо и инициализируем все значения в дереве на 0, они будут иметь значение 0 и, следовательно, не будут влиять на максимум.
источник
Python 2 -
O(n^2)
- 114 байтисточник
C ++ -
O(n log n)
- 261 байтДолжно быть исправлено сейчас:
источник
auto S=set<pair<I,I>>();
длиннее, чем простоset<pair<I,I>> S;
.#define I int
длиннее чемusing I=int;
. Нет необходимости присваиватьn
что-либо, вы можете заменитьauto n=*prev(S.lower_bound({w,-1}));I y=n.second
наI y=prev(S.lower_bound({w,-1}))->second+w;
.S
очень запутанная, вы можете просто отказаться от вставки и использованияstd::set<std::pair<int,int>>S{{-1,0}};
.using namespace std;using I=int;I h(vector<I>l){I W=0;set<pair<I,I>>S{{-1,0}};for(I w:l){I y=prev(S.lower_bound({w,-1}))->second+w;W=max(W,y);S.insert({w,y});}return W;}
std::max
, используйтеW=y>W?y:W;
.Matlab, O ( n 2 n ), 90 байт
Примеры:
источник
Python, O (2 n ), 91 байт
Это больше для развлечения, чем для соревнования. Тайное рекурсивное решение:
источник
max(m,l[0])
учитывая, чтоnot(l[0]<m)
это простоl[0]
, конечно?