Хорошо, мой первый ответ довольно неудачен, поэтому я подумал, что попробую несколько разных способов сделать это и сообщу о различиях. Вот мой код.
import sys
import itertools
def getFirstDup(c, toTest):
# Original idea using list slicing => 5.014 s
if toTest == '1':
for i in xrange(0, len(c)):
if c[i] in c[:i]:
return c[i]
# Using two sets => 4.305 s
elif toTest == '2':
s = set()
for i in c:
s2 = s.copy()
s.add(i)
if len(s) == len(s2):
return i
# Using dictionary LUT => 0.763 s
elif toTest == '3':
d = {}
for i in c:
if i in d:
return i
else:
d[i] = 1
# Using set operations => 0.772 s
elif toTest == '4':
s = set()
for i in c:
if i in s:
return i
else:
s.add(i)
# Sorting then walking => 5.130 s
elif toTest == '5':
c = sorted(c)
for i in xrange(1, len(c)):
if c[i] == c[i - 1]:
return c[i]
# Sorting then groupby-ing => 5.086 s
else:
c = sorted(c)
for k, g in itertools.groupby(c):
if len(list(g)) > 1:
return k
return None
c = list(xrange(0, 10000000))
c[5000] = 0
for i in xrange(0, 10):
print getFirstDup(c, sys.argv[1])
По сути, я пробую это шестью разными способами, как указано в исходном файле. Я использовал команду Linux time
и собрал среды выполнения в реальном времени, выполнив команды так:
time python ./test.py 1
с 1
- какой алгоритм я хотел попробовать. Каждый алгоритм ищет первый дубликат в 10 000 000 целых чисел и выполняется десять раз. В списке есть одно дублирование, которое «в основном отсортировано», хотя я попробовал отсортированные списки в обратном порядке, не замечая пропорциональной разницы между алгоритмами.
Мое первоначальное предложение не сработало за 5,014 с. Мое понимание решения icyrock.com также плохо сказалось на 4,305 с. Затем я попытался использовать словарь для создания LUT, который дал наилучшее время выполнения при 0,763 с. Я попытался использовать оператор in
на множествах и получил 0,772 с, почти столько же, сколько словарь LUT. Я попытался отсортировать и пройтись по списку, что дало жалкое время 5,130 с. Наконец, я попробовал предложение Джона Мачина о itertools, что дало плохое время 5,086 с.
Таким образом, словарь LUT , кажется, является подходящим способом, с операциями над множествами (которые могут использовать LUT в его реализации), являющимися секундой закрытия.
Обновление: я попробовал предложение распейции, и кроме того факта, что вам нужно точно знать, какой дублирующий ключ вы ищете, реальный алгоритм пока что хуже всего (66,366 с).
Обновление 2: я уверен, что кто-то скажет, что этот тест необъективен, поскольку дублирующее местоположение находится рядом с одним концом списка. Попробуйте запустить код в другом месте, прежде чем понижать голосование, и сообщите о своих результатах!