2016-10-15 3 views
3

Проблема, с которой я столкнулся, заключается в поиске/проверке элементов в списке с сложностью O (1). Ниже имеет сложность O (N):Большинство Pythonic способ найти/проверить элементы в списке с O (1) сложностью?

'foo' in list_bar 

Это имеет сложность O (N), потому что вы используете ключевое слово in на list. (Обратитесь к Python Time Complexity)

Однако, если вы используете ключевое слово in на set, оно имеет сложность O (1).

Причина, по которой мне нужно выяснить сложность O (1) для списка, а не набора, во многом объясняется необходимостью учета дубликатов элементов в списке. Наборы не допускают дублирования. Достойный пример был бы:

chars_available = ['h', 'e', 'l', 'o', 'o', 'z'] 
chars_needed = ['h', 'e', 'l', 'l', 'o'] 

def foo(chars_available, chars_needed): 
    cpy_needed = list(chars_needed) 
    for char in cpy_needed: 
     if char in chars_available: 
      chars_available.remove(char) 
      chars_needed.remove(char) 
     if not chars_needed: return True # if chars_needed == [] 
    return False 

foo(chars_available, chars_needed) 

пример не фокус здесь, поэтому, пожалуйста, постарайтесь не отвлекаться на него. Основное внимание по-прежнему пытается получить сложность O (1) для поиска элементов в списке. Как я мог бы выполнить это на питоническом уровне?

(В качестве дополнительного кредита, если вы хотите показать лучший способ выполнения этой операции в Python, псевдокоде или другом языке, я был бы рад прочитать его).

Спасибо!

Edit:

В ответ на ответ Ами Tavory, я узнал, вы не можете сделать списки быстрее, чем O (N), но предложение для collections.Counter() помогли решить приложение я работал. Я загружаю свое быстрое решение для Stack Overflow, производительность была феноменальной! Если я не ошибаюсь (исправьте меня, если я ошибаюсь), это должно быть O (1), поскольку оно включает только хешируемые значения и без итерации цикла.

from collections import Counter 
chars_available = ['h', 'e', 'l', 'o', 'o', 'z'] 
chars_needed = ['h', 'e', 'l', 'l', 'o'] 

def foo(chars_available, chars_needed): 
    counter_available = Counter(chars_available) 
    counter_needed = Counter(chars_needed) 
    out = counter_needed - counter_available 
    if not list(out.elements()): return True 
    else: return False 

foo(chars_available, chars_needed) 

Очень быстро, очень pythonic! Благодаря!

+0

Вы можете сохранить как список и набор, есть некоторые структуры данных, которые могли бы удовлетворить вас, но они могли бы сделать некоторые компромиссы, такие как потеря порядка первоначального списка. –

+1

Чтобы найти элемент в списке, вы должны использовать алгоритм поиска. Набор в основном реализуется как карты Hash, и из-за этого они позволяют иметь O (1). – n3m4nja

+0

Является ли это чисто теоретическим интересом или существует практическое применение, где вам это нужно? –

ответ

7

В общем, невозможно найти элементы в list в постоянное время. Вы могли гипотетически поддерживать как list, так и set, но операции по обновлению потребуют линейного времени.

Вы сказали, что ваша мотивация

список, а не множество, в основном в связи с необходимостью учета дублирующих элементов в списке. Наборы не допускают дублирования.

и попросите не сосредотачиваться на этом примере. Если это ваша мотивация, вы можете использовать вместо set, dict, сопоставляя каждый элемент с числом его вхождений.

Вы могли бы найти collections.Counter полезно, в частности:

In [1]: from collections import Counter 

In [2]: Counter(['h', 'e', 'l', 'o', 'o', 'z']) 
Out[2]: Counter({'e': 1, 'h': 1, 'l': 1, 'o': 2, 'z': 1}) 
+0

Хорошо, хорошо знать, что о списках. Комментарий nemanjaps в моем вопросе помог прояснить некоторые вещи о списках и настроить тоже. Это довольно приятная альтернатива списку. Хотя я, очевидно, не буду использовать это для всего, это может быть то, что мне нужно для больших операций без использования внешних библиотек. – dysfunctional

+0

Я отредактировал мой вопрос в ответ на ваш ответ! Это было отличное решение, помогло мне многое с проблемой, с которой я столкнулся, а также с пониманием сложности времени со списками для будущих проблем! Большое спасибо :) – dysfunctional

Смежные вопросы