Почему HashSet быстрее, чем Array в этой проблеме с повторяющимися целыми числами?

Я новичок в изучении структур данных и алгоритмов и начинаю решать задачи NeetCode 150. Первая проблема, с которой я столкнулся, была несложной, я понимаю, почему она работает, но мне любопытно, почему лучшее решение предполагает использование HashSet вместо массива.

Я уверен, что речь идет о временной сложности, а это тема, которую мне трудно понять, поэтому я надеюсь, что кто-нибудь сможет дать мне простое объяснение, почему одно решение лучше другого, и будет ли оно действительно таковым. плохо использовать здесь массив вместо HashSet (если бы я использовал его в интервью, им бы это не понравилось).

Это решение, которое я придумал. Он практически идентичен, за исключением использования массивов и .append() вместо HashSet и .add(). Решение было технически правильным, но, судя по проведенным мной исследованиям, решение HashSet оказалось лучше/быстрее, и мне нужна помощь, чтобы понять, почему.

class Solution:
    def hasDuplicate(self, nums: List[int]) -> bool:
        newArray = []
        for i in nums:
            if i in newArray:
                return True
            newArray.append(i)    
        return False

Вот самое лучшее решение.

class Solution:
    def hasDuplicate(self, nums: List[int]) -> bool:
        hashset = set()

        for n in nums:
            if n in hashset:
                return True
            hashset.add(n)
        return False

В чем различия? Также какое влияние окажет добавление nums.sort() на первый подход? Изменит ли это каким-либо образом время выполнения? Извините, если эти вопросы до боли очевидны, мне просто нужна помощь, чтобы разобраться в этих концепциях.

Одним из основных преимуществ набора является то, что: if n in hashset не нужно перебирать каждый элемент, а здесь: if i in newArray. По мере того, как newArray становится длиннее, это занимает больше времени, потому что нужно начинать с самого начала и просматривать каждый элемент, пока не будет найдено совпадение.

Mark 19.08.2024 17:52

Если быть точным: У вас нет массива . У вас есть список.

Matthias 19.08.2024 17:56
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Давайте рассмотрим использование оператора in в операторе if.

Для массива операция in является операцией O(n) — элементы массива просматриваются последовательно, а в худшем случае (т. е. если искомый элемент отсутствует в массиве) он перебирает весь массив. Для хэш-набора операция in является операцией O(1) — рассматриваемый элемент хешируется и проверяется по правому сегменту хэша (предостережение: это предполагает, что алгоритм хеширования является правильным, что в случае целых чисел должно быть).

Что касается сортировки, давайте начнем с самого простого: второй подход, использующий хеш-набор, представляет собой алгоритм O(n) (n элементов, каждый из которых имеет операцию O(1) для проверки того, находятся ли они в хеш-наборе, и если нет, добавьте их). Сортировка num будет операцией O(nlog(n)), поэтому здесь она точно не поможет.

При первом подходе, где используется массив, он в конечном итоге тоже не поможет. Во-первых, давайте поймем временную сложность этого решения. nums имеет n элементов, для каждого из которых ищется вспомогательный массив. Для первого элемента ищется массив нулевого размера, для второго — массив размера 1 и так далее. В конечном итоге это имеет сложность log(n), а поскольку это делается для n элементов, общая сложность равна O(nlog(n)). Таким образом, добавление сортировки определенно не улучшит решение на порядок.

Это мне очень помогло, спасибо. Я боролся с тем, что именно делает/назначает HashSet. Я исследовал это заранее и понял разницу, но не понял, что он хранит уникальные элементы и в правильном порядке (по крайней мере, для целых чисел я пока уверен в других типах данных).

Hisham Issa 19.08.2024 18:10

«В конечном итоге это имеет сложность log(n)» - Хм? Как же так? Почему бы и нет?

no comment 19.08.2024 18:17

@HishamIssa Наборы неупорядочены, не имеют «правильного порядка».

no comment 19.08.2024 18:19

В Python наборы представляют собой хеш-таблицы, в которых быстрее проверить существование элемента. Его сложность O(1), потому что вы проверяете, взят индекс n или нет, в отличие от массивов, где вы проходите через каждый элемент, что приводит к сложности O(n).

Другие вопросы по теме

Экономия $! (идентификатор процесса последней фоновой команды) как элемент массива
Есть ли эффективный способ извлечь фрагмент трехмерного массива?
Создайте новую матрицу с суммой всех подматриц n*n без использования циклов
Как создать случайную сложную симметричную унитарную матрицу в Python?
Могу ли я заменить имя массива на переменную и добавить к ней значение?
Есть ли в массивах NumPy синтаксис для установки значения в последнем измерении на основе первого измерения?
Как создать массив из определенных частей данных JSON?
Уменьшите двухмерный массив истории изменений до начальных и конечных значений для каждого идентификатора и удалите строки, в которых нет изменений
C++ Существует ли быстрый многомерный массив, который позволяет использовать подмассивы разного размера?
PowerShell — наиболее эффективный способ создания массива/списка массивов/pscustomobject