Чтобы проанализировать асимптотическое время выполнения вашего кода, вам также необходимо знать время выполнения каждой из функций, которые вы вызываете. Обычно мы думаем об арифметических выражениях, таких как сложение, как о постоянном времени (O (1)), поэтому ваша первая функция имеет два цикла for для элементов n
, а тело цикла занимает только постоянное время, выходя в O (n * n *). 1) = O (n ^ 2).
Вторая функция имеет только одну функцию for loop, но проверка членства для списка является функцией O (n) по длине списка, поэтому у вас все еще есть O (n * n) = O (n ^ 2). Последний вариант все еще может быть быстрее (возможно, Python оптимизировал код для проверки членства в списке), но он не будет асимптотически быстрее (время выполнения по-прежнему увеличивается в квадрате в n
).
EDIT - как указал @Mark_Meyer, ваша вторая функция на самом деле O (1), потому что в ней есть ошибка; извини, я просмотрел это и не заметил. Этот ответ предполагает исправленную версию второй функции, например
def optimized_can_get_value(lst, k=17):
for x in lst:
if k - x in lst:
return True
return False
(Примечание. У вас нет значения по умолчанию для вашей функции, которая может быть изменяемой. См. этот вопрос SO о возможных проблемах. Я также удалил временный список, потому что в этом нет необходимости; в любом случае он просто указывал на один и тот же объект списка.)
РЕДАКТИРОВАТЬ 2: для забавы, вот пара из O (n) решений этого (оба используют, что проверка сдерживания для набора является O (1)).
Однострочник, который по-прежнему останавливается, как только найдено решение:
def get_value_one_liner(lst, k):
return any(k - x in set(lst) for x in lst)
- РЕДАКТИРОВАТЬ 3: Я думаю, что это на самом деле O (n ^ 2), потому что мы называем
set(lst)
для каждого x
. Я думаю, что использование выражений присваивания в Python 3.8 может дать нам одну строчку, которая все еще эффективна. У кого-нибудь есть хороший Python <3.8 с одной строкой? </li>
И версия, которая пытается не выполнять дополнительную работу путем создания набора по ходу дела (не уверен, что это на самом деле быстрее на практике, чем создание всего набора в начале; это, вероятно, зависит от фактических входных данных):
def get_value_early_stop(lst, k):
values = set()
for x in lst:
if x in values:
return True
values.add(k - x)
return False