Разбор задачи: Пересечение двух связанных списков

Вид объекта - Связанный список:

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

Предложенный нами код решения:

def get_intersection_node(headA, headB):
    """
    Находит узел пересечения двух связанных списков.

    :param headA: Начальный узел первого списка.
    :param headB: Начальный узел второго списка.
    :return: Узел пересечения или None, если пересечения нет.
    """
    if not headA or not headB:
        return None

    pointerA, pointerB = headA, headB

    while pointerA != pointerB:
        pointerA = pointerA.next if pointerA else headB
        pointerB = pointerB.next if pointerB else headA

    return pointerA

Пошаговый разбор:

  1. Инициализация указателей:
    • pointerA начинает обход с headA (начала первого списка).
    • pointerB начинает обход с headB (начала второго списка).
  2. Цикл сравнения узлов:
    • На каждой итерации указатели pointerA и pointerB сравниваются.
    • Если они равны, то это точка пересечения, и она возвращается.
  3. Переключение указателей:
    • Если указатель pointerA достигает конца списка A, он переключается на начало списка B.
    • Если указатель pointerB достигает конца списка B, он переключается на начало списка A.
  4. Завершение цикла:
    • Цикл завершится, если указатели встретятся на одном узле (точке пересечения) или оба станут None (если пересечения нет).
  5. Возврат результата:
    • Если пересечение найдено, возвращается узел пересечения.
    • Если пересечения нет, возвращается None.

Как работает переключение указателей?

Пример пересекающихся списков:

listA: 4 -> 1 -> 8 -> 4 -> 5  
                 ↘
listB:      5 -> 6 -> 1
  1. Итерация 1:
    • pointerA на узле 4, pointerB на узле 5. Узлы разные.
  2. Итерация 2:
    • pointerA на узле 1, pointerB на узле 6. Узлы разные.
  3. Итерация 3:
    • pointerA на узле 8, pointerB на узле 1. Узлы разные.
  4. Итерация 4:
    • pointerA на узле 4, pointerB переключается на 4 (начало listA).
  5. Итерация 5:
    • pointerA на узле 5 (начало listB), pointerB на узле 1.
  6. Итерация 6:
    • Оба указателя встречаются на узле 8. Это пересечение.

Пример списков без пересечения:

listA: 2 -> 6 -> 4  
listB: 1 -> 5
  1. Указатели проходят списки полностью.
  2. После переключения на противоположные списки указатели снова проходят их.
  3. После двух полных проходов указатели оба становятся None. Это подтверждает отсутствие пересечения.

 



Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии