#python #performance #set
Вопрос:
Я учусь писать на python с помощью этого веб-сайта, используя HankerRank. Я столкнулся с этой проблемой, и код, который я написал, не прошел несколько тестов из-за превышения лимита времени. Поэтому я зашел на YouTube и использовал учебник, и его код работал, но я не понимаю, почему его код более эффективен, чем мой. Если кто-нибудь сможет объяснить, я буду вам очень признателен.
Мой Код:
room=list(map(int, input().split()))
room.sort()
roomset=set(room.copy())
for i in roomset:
if room.count(i)!=K:
print(i)
else:
continue
Код учебника:
room=list(map(int, input().split()))
room.sort()
a=set()
b=set()
for i in room:
if i not in a:
a.add(i)
b.add(i)
else:
b.discard(i)
for o in b:
print(o)
Комментарии:
1.
room.count(i)
равно O(n) для размера комнаты
Ответ №1:
Причина, по которой ваш код работает медленно, заключается в том, что на каждой итерации вашего цикла python должен сканировать весь список, чтобы подсчитать, сколько раз появляется это число. Это означает, что в худшем случае количество операций растет с квадратом размера ввода, что занимает много времени.
Код учебника просто содержит набор чисел, которые встречались по крайней мере один раз ( a
), и набор чисел, которые встречались ровно один раз ( b
). Все операции набора для вставки, удаления и проверки принадлежности являются постоянными по времени, поэтому время их алгоритма линейно увеличивается с длиной входных данных.
Комментарии:
1. Я понимаю. Спасибо за объяснение
Ответ №2:
Потому что для цикла и комнаты.count(i) дает O(n) * O(n) = O(n**2) временную сложность. В то время как учебное решение равно O(n)
Ответ №3:
Превышение времени означает, что вы выполняете больше работы, чем требуется.
room.sort()
— зачем вам sort
список номеров комнат? Код не использует никаких преимуществ этого. (странно, другой код делает то же самое, я что-то упустил?)
roomset=set(room.copy())
— нет необходимости делать копию
Но главная проблема в том, что вопрос не в том, сколько раз номер комнаты присутствует в списке?, а точнее: это точно 1?. Если вы сталкиваетесь с номером комнаты во второй раз, у вас есть ответ, и вы должны прекратить считать.
Более эффективный код делает именно это. Он запоминает, видел ли он номер комнаты (набор a
) и было ли это первое появление (набор b
). Никакого подсчета, т. е. достаточно просмотреть список всего один раз — это важное повышение эффективности. После изучения всех чисел набор b
содержит только элементы с ровно одним появлением.