Рубрики
Без рубрики

Нахождение дубликата номера – LeetCode # 287 – Python

Приветствую сопутствующую devs! Надеюсь, у вас все хорошо, несмотря на всю пандемию ситуацию и оставаться H … Теги с Python, проблемным, лезодом, начинающими.

Приветствую сопутствующую devs!

Надеюсь, у вас все хорошо, несмотря на всю пандемию ситуацию и оставаться здоровыми.

Я хотел написать об этом очень интересном/сложном решении проблемы, которую я узнал сегодня.

Нахождение дубликата числа в массиве/списке.

До чего-либо я бы побудил вас взглянуть на Заявление о проблеме LeetCode Отказ

И попытаться решить это. Не имеет значения, если вы не можете это сделать. Это чрезвычайно странная проблема.

Данное

  • Список номеров содержит N + 1 целые числа.
  • И каждое число в числовых номерах имеет диапазон, 1..n (включительно).
  • В списке только один дубликат номер.

Разные решения

  1. Имейте через список и сортируйте его, а затем найдите, если два соседних числа равны и возвращают один из этих номеров.
  2. Храните видимые номера в другом списке, а затем возвращайте Num, если NUM уже видно.

Также следить за проблемой

  • Космическая сложность должна быть O (1) – постоянное пространство.
  • Сложность времени должна быть меньше, чем O (n ^ 2) Отказ

Вот, хорошо. На решения, которые соответствуют последующему примечанию.

Я видел Бинарный поиск Быть перечисленным в качестве решения, вероятно, чтобы уменьшить временную сложность на половину (так o (log n)) с постоянной сложностью пространства. Но я был более заинтересован в другом решении, и это было немного сложно. Почему-то, мне потребовалось около дня, чтобы понять это.

nums = [2,6,4,1,3,1,5] Выход – 1.

Идея состоит в том, чтобы иметь два указателя – медленно и быстро . Они будут перемещаться через список, используя текущий номер в качестве индекса к следующему элементу для перебрызгивания. И как всегда, быстро Перемещает два шага впереди медленно Отказ Итерации создают связанный список, который содержит цикл из-за дубликата элемента.

Итак, эта проблема превращается в Проблема нахождение цикла в подключенном списке.

Новое заявление о проблеме Учитывая связанный список, найдите входной узел/элемент цикла.

Почему мы должны найти отправной точкой цикла?

Читать дальше.

Создание нашего связанного списка Теперь мы нашли бы Последовательность чисел путем итерации через Nums (Приведено выше) и создание связанного списка. Дубликат будет иметь одинаковое значение и ссылку назад к исходному значению, создающим цикл. Объяснение того, как указано каждое следующее число, упоминается в () рядом с числом.

[2,6,4,1,3,1,5]

Вы начинаете с первого элемента.

2 -> 4 (Nums [2]) -> 3 (Nums [4]) -> 1 (nums [3]) -> 6 (nums [1]) – > 5 (Nums [6]) -> 1 (Nums [5]) -> 6 (Nums [1]) – > 5 (Nums [6]) -> 1 (Nums [5]) -> ….

И эта последовательность просто продолжается. Это цикл. Когда мы видим это, мы будем похожи, черт возьми, теперь, где этот цикл начинается!?

Хорошо, хорошо, давайте сначала построим визуальную помощь связанного списка из этого.

Благодаря Леткоде у нас есть здесь.

Сейчас для подхода

Дублирующий элемент является входом в цикл, присутствующий в списке цифр. Подожди, whaaaat?

Два шага

  1. Найти, если есть петли – Во время итерации через список, если в какой-то момент и медленно и быстро Указатели указывают на тот же узел, то да, цикл присутствует. С быстро движется два узла впереди, быстро и медленно будет указывать на тот же узел Только если есть петли Отказ

  2. Найдите начальный узел цикла.

как нам это сделать? Также, так как мы нашли узел, где оба быстро и медленно Укажите, не могли бы мы просто вернуть это?

Ну нет.

Почему? Узел пересечения не обязательно является дубликатом элемента/узла, поскольку этот узел пересечения является узлом в цикле, где быстро догнал медленно или где быстро и медленно Указатели случайно встречались – это просто доказывает, что в связанном списке есть цикл.

Чтобы получить точный дублирующий элемент, нам нужно увидеть, где возникла этот цикл/цикл.

Чтобы найти это происхождение, нам нужно подтолкнуть медленно Указатель на начало списка и переместить оба быстро и медленно Указатели с той же скоростью, по одному за раз, и когда теперь они встречаются в том же узле, это начало цикла/цикла.

Некоторые математические вещи Предполагая D Количество шагов/расстояние от начала связанного списка к началу цикла и K Количество шагов/расстояние от начала цикла на точку пересечения Мы определили на шаге 1. С медленно Перемещение к началу (0), его позиция после D Шаги – это Подразделение . быстро Указатель продолжается с точки пересечения, поэтому его положение после D Шаги будут, NC (некоторое количество циклов) – K, который равен d => NC -.

Сейчас Мы получили это разобралось, время, чтобы наконец-то кодировать это!

class Solution:
    def findDuplicate(self, nums: List[int]) -> int:     
        slow = nums[0]
        fast = nums[0]
        while True:
            slow = nums[slow]
            fast = nums[nums[fast]]
            if slow == fast:
                break    
        slow = nums[0]
        while slow != fast:
            slow = nums[slow]
            fast = nums[fast]   
        return fast

Ресурсы, чтобы пройти, если вы застряли во время борьбы с пониманием этого решения

  1. Гаурав Сен потрясающий видео При нахождении запуска цикла в связанном списке. Смотрите это, по крайней мере, дважды, и вы поймете.
  2. Алгоритм обнаружения цикла Флойда на Википедии.
  3. Это Действительно крутое решение.
  4. Nick White’s Video Чтобы понять, что даже крутые YouTubers борются с этой проблемой.
  5. Кроме того, очень важно понимать разницу между Найти, существует ли цикл/цикл в связанном списке и Нахождение, где вход/стартовый узел цикла является Отказ
  6. Также Это Ответ StackoverFlow – это источник многих ответов на вопросы в процессе обучения.
  7. Конечно, посмотрите на объяснение решения лецкода.

Большое спасибо за чтение. Это решение проблемы было трудно понять, SOO, если вы застряли в процессе обучения (я тоже был!), Дайте мне знать, может быть, я могу помочь.

Оригинал: “https://dev.to/chethanagopinath/finding-the-duplicate-number-leetcode-287-python-3dmp”