Объясните поведение и асимптотику следующей функции на Python, найдите её недостатки и предложите как минимум два разных способа улучшения по времени и/или памяти, сохранив порядок элементов: def remove_dups(lst): res = [] for x in lst: if x not in res: res.append(x) return res

2 Окт в 13:42
10 +1
0
Ответы
1

Функция, которую вы привели:

def remove_dupslstlstlst:
res = for x in lst:
if x not in res:
res.appendxxx return res

Что она делает

Возвращает новый список, содержащий первые вхождения элементов из lst, т.е. удаляет повторяющиеся элементы, сохраняя порядок появления stable,keep−firststable, keep-firststable,keepfirst.

Асимптотика и недостатки

Время: On2n^2n2 в худшем и типичном случае. Причина: проверка "x not in res" — поиск по списку занимает Okkk, где k — текущий размер res; в среднем суммарно получается ~1 + 2 + ... + u = Ou2u^2u2 ≤ On2n^2n2 u—числоуникальных,n—длинаисходногоu — число уникальных, n — длина исходногоuчислоуникальных,nдлинаисходного.Память: Ouuu дополнительной памяти для результата res u≤nu ≤ nun.Другие недостатки:
Очень медленная на больших списках.Если элементы хешируемы, есть более быстрые варианты — текущее решение их не использует.Работает с любыми включаянепереставляемыевключая непереставляемыевключаянепереставляемые элементами, но это преимущество ценой производительности.

Как минимум два улучшения ссохранениемпорядкас сохранением порядкассохранениемпорядка:

1) Использовать множество "seen" для проверки вхождений быстрое;требуетхешируемыхэлементовбыстрое; требует хешируемых элементовбыстрое;требуетхешируемыхэлементов Код:
def remove_dups_hashablelstlstlst:
seen = set res = for x in lst:
if x not in seen:
res.appendxxx seen.addxxx return res

Асимптотика:

Время: Onnn в среднем поамортизированнойстоимостихеш−операцийпо амортизированной стоимости хеш-операцийпоамортизированнойстоимостихешопераций. В редких творческих атакующих сценах или при множестве коллизий можно получить деградацию до On2n^2n2, но на практике — Onnn.Память: Ouuu для seen + Ouuu для res.

Плюсы: очень быстро; простой код.
Минусы: элементы должны быть хешируемы например,несписки/словарянапример, не списки/словарянапример,несписки/словаря. Использует дополнительный set.

2) Использовать dict.fromkeys короткоиэффективно,используетхешированиекоротко и эффективно, использует хешированиекороткоиэффективно,используетхеширование Код Python3.7+гарантируетсохранениепорядкаключейPython 3.7+ гарантирует сохранение порядка ключейPython3.7+гарантируетсохранениепорядкаключей:
def remove_dups_dictlstlstlst:
return listdict.fromkeys(lst)dict.fromkeys(lst)dict.fromkeys(lst)

Асимптотика:

Время: Onnn в среднем.Память: Ouuu для словаря + итоговый список Ouuu.

Плюсы: минималистичный один вызов, быстро.
Минусы: требует хешируемых элементов.

3) In-place вариант с двумя указателями уменьшаетдополнительнуюпамятьдлярезультирующегоспискауменьшает дополнительную память для результирующего спискауменьшаетдополнительнуюпамятьдлярезультирующегосписка Если хотите не выделять новый список res экономияпамятинаодномспискеэкономия памяти на одном спискеэкономияпамятинаодномсписке, но при этом всё ещё пользоваться set для быстрого поиска:
def remove_dups_inplacelstlstlst:
seen = set write = 0
for read in rangelen(lst)len(lst)len(lst):
x = lstreadreadread if x not in seen:
seen.addxxx lstwritewritewrite = x
write += 1

удалить хвостdel lstwrite:write:write: return lst

Асимптотика:

Время: Onnn в среднем.Память: Ouuu для seen; нет отдельного списка res памятьнарезультат—висходномспискепамять на результат — в исходном спискепамятьнарезультатвисходномсписке.

Плюсы: экономия памяти при большом исходном списке несоздаёмвторойсписоктакогожеразмеране создаём второй список такого же размеранесоздаёмвторойсписоктакогожеразмера.
Минусы: модифицирует входной список; требует хешируемых элементов.

4) Для непереставляемых/нехешируемых элементов
Если элементы могут быть не хешируемыми например,спискинапример, спискинапример,списки и нужно сохранять именно их неприводитькдругомутипуне приводить к другому типунеприводитькдругомутипу, варианты:

Оставить On2n^2n2 решение вашеначальноеваше начальноевашеначальное — корректно, но медленно.

Преобразовать элементы в представление, которое можно хешировать например,tuple(x)длясписковнапример, tuple(x) для списковнапример,tuple(x)длясписков и использовать seen для этих ключей, при этом добавлять в res оригинальные объекты:
def remove_dups_by_reprlstlstlst:
seen = set res = for x in lst:
key = reprxxx # или tuplexxx / json.dumpsxxx — в зависимости от случая
if key not in seen:
seen.addkeykeykey res.appendxxx return res
Внимание: repr/json/serializing могут быть медленными и потенциально небезопасными/рискованными коллизии,разныеобъектысодинаковымrepr,чувствительностькпорядкуключейвсловаряхит.п.коллизии, разные объекты с одинаковым repr, чувствительность к порядку ключей в словарях и т.п.коллизии,разныеобъектысодинаковымrepr,чувствительностькпорядкуключейвсловаряхит.п.

Альтернатива: использовать OrderedDict и попытаться вставлять ключи, но всё равно ключи должны быть хешируемыми.

5) Для особых доменов данных целыевузкомдиапазонецелые в узком диапазонецелыевузкомдиапазоне Если значения — целые из известного относительно небольшого диапазона, можно применять битовые таблицы/массивы булевых флагов для уменьшения памяти и ускорения до Onnn с меньшими накладными расходами, чем set.

Резюме и рекомендации

Если элементы хешируемы чащевсеготакчаще всего такчащевсеготак: используйте seen = set вместе с res вариант1вариант 1вариант1 или удобный dict.fromkeys вариант2вариант 2вариант2. Это даёт Onnn время и простоту.Если нужно экономить память на новом списке — используйте in-place алгоритм вариант3вариант 3вариант3.Если элементы не хешируемы и нельзя конвертировать безопасно, остаётся On2n^2n2 вариант либо предварительная сериализация в хешируемую форму соговоркамис оговоркамисоговорками.Избегайте сортировки потеряпорядкапотеря порядкапотеряпорядка и вероятностных структур bloomfilterbloom filterbloomfilter если необходима точная детерминированная фильтрация без ложных положительных результатов.

Если хотите, могу привести готовые оптимальные реализации с тестами и примерами для ваших конкретных типов данных.

2 Окт в 14:25
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир