#algorithm #data-structures
#алгоритм #структуры данных
Вопрос:
в настоящее время я прохожу курс ds amp; a udemy, поскольку готовлюсь к интенсивному набору этой предстоящей осенью. я наткнулся на проблему, которая подсказала примерно следующее:
«Учитывая массивы списков, выясните, какое целое число отсутствует во втором массиве списков, которое присутствовало в первом массиве списков»
В курсе было дано два решения, одно из которых считалось решением грубой силы, а другое — более оптимальным.
Вот несколько решений:
def finderBasic(list1,list2):
list1.sort()
list2.sort()
for i in range(len(list1)):
if list1[i] != list2[i]:
return list1[i]
def finderOptimal(list1,list2):
d = collections.defaultdict(int)
for num in list2:
d[num] = 1
for num in list1:
if d[num] == 0:
return num
else:
d[num] -= 1
В курсе объясняется, что finderOptimal является более оптимальным способом решения задачи, поскольку он решает ее в O (n) или линейно. Может ли кто-нибудь, пожалуйста, подробнее объяснить мне, почему это так. Мне просто показалось, что finderBasic был намного проще и проходил только через один цикл. Любая помощь была бы очень признательна, спасибо!
Комментарии:
1. Обе реализации неверны, если вы не ограничите входные данные. Второй сбой при [1, 1, 2], [1, 1]. Первый сбой при [1], [0, 1]. Второй вариант особенно плох, потому что он добавляет код, который выглядит так, как будто предназначен для работы с дубликатами.
2.
set(list1) - set(list2)
дает все целые числа, которые находятся в первом списке, которые не отображаются во втором списке.3. На самом деле, первое решение завершается неудачей
list1=[1, 2, 3]; list2=[1, 2]
с исключением индекса.
Ответ №1:
Вы были бы правы, если бы речь шла только о прохождении цикла, первое решение было бы лучше. — как вы сказали, прохождение одного цикла for (целиком) занимает O (n) времени, и не имеет значения, проходите ли вы его один, два или c-раз (до тех пор, пока c достаточно мал).
Однако тяжелая операция здесь — сортировка, поскольку она занимает примерно n * log (n) времени, что больше, чем O (n). Это означает, что даже если вы дважды запустите цикл for во 2-м решении, это все равно будет намного лучше, чем сортировка один раз.
Пожалуйста, обратите внимание, что доступ к ключу словаря занимает приблизительно O (1) времени, поэтому время по-прежнему равно O (n) времени цикла.
См.:https://wiki .python.org/moin/TimeComplexity
Базовое решение может быть лучше для читателя, поскольку оно очень простое и прямолинейное, однако оно более сложное.
Ответ №2:
Отказ от ответственности: я не знаком с Python.
Есть два цикла, которые вы не учитываете в первом примере. Каждый из этих sort()
вызовов будет иметь как минимум два вложенных цикла для реализации сортировки. Кроме того, обычно наилучшая производительность, которую вы можете получить в общем случае, — это O (n log (n)) при выполнении сортировки.
Во втором случае избегается любая сортировка и просто используется «игровая карточка» для обозначения того, что присутствует. Кроме того, он использует словарь, который является хэш-таблицей. Я уверен, что вы уже узнали, что хэш-таблицы предлагают операции с постоянным временем O(1).
Более простое не всегда означает наиболее эффективное. И наоборот, эффективное часто трудно понять.