Вы должны перебрать перечисленный список и добавить каждый элемент к набору "видимых" элементов и добавить индекс в выходной список , если элемент еще не был просмотрен (отсутствует в «увиденный» набор).
О, имя input
переопределяет встроенную функцию input()
, поэтому я переименовал ее input_list
.
output = []
seen = set()
for i,e in enumerate(input_list):
if e not in seen:
output.append(i)
seen.add(e)
, что дает output
как [0, 1, 2, 5, 6, 8]
.
зачем использовать набор?
Вы можете подумать, зачем использовать набор, если вы можете сделать что-то вроде:
[i for i,e in enumerate(input_list) if input_list.index(e) == i]
, который будет работать, потому что .index
возвращает вам индекс первого элемента в списке с этим значением, поэтому если вы проверите индекс элемента по этому, вы можете утверждать, что это первое вхождение этого элемента и отфильтруйте те элементы, которые не являются первыми вхождениями.
Однако это не так эффективно, как использование набора, потому что list.index
требует, чтобы Python перебирал список, пока не найдет элемент (или не найдет). Эта операция сложна на O(n)
, и поскольку мы вызываем ее для каждого элемента в input_list
, полное решение будет O(n^2)
.
С другой стороны, использование набора, как в первом решении, дает решение O(n)
, потому что проверка, является ли элемент in
, является сложностью O(1)
(средний случай). Это связано с тем, как наборы реализованы (они похожи на списки, но каждый элемент хранится по индексу его хеша, так что вы можете просто вычислить хеш элемента и посмотреть, есть ли там элемент для проверки членства, а не для перебора заметьте, что это смутное упрощение, но это их идея).
Таким образом, поскольку каждая проверка на членство равна O(1)
, и мы делаем это для каждого элемента, мы получаем решение O(n)
, которое намного лучше, чем O(n^2)
решение.