Проблема: →

Учитывая заголовки двух односвязных списков headA и headB, вернуть узел, в котором два списка пересекаются. Если два связанных списка вообще не пересекаются, вернуть null.

Например, следующие два связанных списка начинают пересекаться в узле c1:

Тестовые примеры генерируются таким образом, что нигде во всей связанной структуре нет циклов.

Обратите внимание, что связанные списки должны сохранять свою первоначальную структуру после возврата из функции.

Пользовательский судья:

Входные данные для судьи задаются следующим образом (ваша программа не получает эти входные данные):

  • intersectVal - Значение узла, в котором происходит пересечение. Это 0, если нет пересеченного узла.
  • listA - Первый связанный список.
  • listB - Второй связанный список.
  • skipA — Количество узлов, которые нужно пропустить вперед в listA (начиная с головы), чтобы добраться до пересекаемого узла.
  • skipB — количество узлов, которые необходимо пропустить в listB (начиная с головы), чтобы добраться до пересекаемого узла.

Затем судья создаст связанную структуру на основе этих входных данных и передаст две головки, headA и headB, в вашу программу. Если вы правильно вернете пересеченный узел, ваше решение будет принято.

Пример 1:

Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
Output: Intersected at '8'
Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect).
From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
- Note that the intersected node's value is not 1 because the nodes with value 1 in A and B (2nd node in A and 3rd node in B) are different node references. In other words, they point to two different locations in memory, while the nodes with value 8 in A and B (3rd node in A and 4th node in B) point to the same location in memory.

Пример 2:

Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
Output: Intersected at '2'
Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect).
From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.

Пример 3:

Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: No intersection
Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.

Ограничения:

  • Количество узлов listA находится в m.
  • Количество узлов listB находится в n.
  • 1 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA < m
  • 0 <= skipB < n
  • intersectVal равно 0, если listA и listB не пересекаются.
  • intersectVal == listA[skipA] == listB[skipB], если listA и listB пересекаются.

Дополнение. Не могли бы вы написать решение, которое выполняется за O(m + n) времени и использует только O(1) памяти?

Решение: →

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

Давайте разберемся с кодом,

В коде они дали два связанных списка head1 и head2, нам нужно сначала проверить, является ли кто-либо из них или оба пустыми, если да, то мы просто вернем NULL .

Теперь, следующий шаг, инициализируйте два указателя node1 и node2 в head1 и head2.

Теперь нам нужно обойти оба связанных списка, чтобы получить пересечение, мы возьмем цикл while и остановим его, когда оба nodeA и nodeB станут такой же.

Считайте узел 1 узлом А и узел 2 узлом Б.

Первая итерация,

Вторая итерация,

Третья итерация,

Здесь следующий из nodeB равен нулю, поэтому мы указываем nodeB как headA,

Примечание: → Здесь мы можем указать nodeB с помощью headB, но в этом случае итерация будет больше, поэтому для получения быстрого результата мы указываем nodeB с headA и nodeAс headB.

Четвертая итерация,

Пятая итерация,

Шестая итерация,

Здесь условие станет false.

В конце мы можем вернуть любой узел, так как оба узла содержат одинаковое значение,

Наконец, nodeA — наш ответ.

Теперь давайте посмотрим полный исходный код,

Код (Java): →

Код (Питон): →

Сложность времени

Здесь мы просматриваем двусвязный список, поэтому общая временная сложность будет O(m+n).

Космическая сложность

Здесь мы использовали только две переменные, поэтому общая пространственная сложность также будет O(1).

Спасибо, что прочитали эту статью ❤

Если эта статья поможет вам, пожалуйста, похлопайте 👏 этой статье.

Пожалуйста, следите за мной на medium, я буду публиковать полезную информацию, как указано выше.

Инстаграм → https://www.instagram.com/alexmurphyas8/

Твиттер → https://twitter.com/AlexMurphyas8

Если я что-то не так? Позвольте мне в комментариях. Я хотел бы улучшить.