Эффективные методы удаления среднего узла в связанном списке

Связанные списки — это фундаментальные структуры данных, используемые в информатике и программировании. Удаление узла из связанного списка — обычная операция, но удаление среднего узла может оказаться немного более сложной задачей, чем удаление головного или хвостового узла. В этой статье мы рассмотрим различные методы эффективного удаления среднего узла из связанного списка. Мы предоставим примеры кода на Python для иллюстрации каждого метода.

Метод 1: наивный подход
Самый простой метод — пройти по связанному списку, чтобы найти средний узел, а затем удалить его. Однако этот метод требует двух проходов по связанному списку и имеет временную сложность O(n), где n — длина списка.

def delete_middle_node_naive(head):
    slow = fast = head
    prev = None
    while fast and fast.next:
        fast = fast.next.next
        prev = slow
        slow = slow.next
    prev.next = slow.next
    return head

Метод 2: быстрые и медленные указатели
В этом методе используются два указателя, один из которых движется со скоростью вдвое меньшей, чем другой. Когда быстрый указатель достигнет конца списка, медленный указатель будет указывать на средний узел. Этот метод требует только одного прохода по связанному списку и имеет временную сложность O(n).

def delete_middle_node_fast_slow(head):
    slow = fast = head
    prev = None
    while fast and fast.next:
        fast = fast.next.next
        prev = slow
        slow = slow.next
    prev.next = slow.next
    return head

Метод 3: отслеживание размера
В этом методе мы сначала определяем длину связанного списка, просматривая его один раз. Затем мы вычисляем положение среднего узла и удаляем его. Этот подход требует двух проходов по связанному списку, но гарантирует удаление среднего узла за один проход.

def delete_middle_node_with_size(head):
    current = head
    length = 0
    while current:
        length += 1
        current = current.next
    middle_pos = length // 2
    current = head
    prev = None
    for _ in range(middle_pos):
        prev = current
        current = current.next
    prev.next = current.next
    return head

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

def delete_middle_node_change_values(node):
    if not node or not node.next:
        return False
    next_node = node.next
    node.val = next_node.val
    node.next = next_node.next
    return True

Удалить средний узел из связанного списка можно различными способами. Выбор метода зависит от таких факторов, как временная сложность, использование памяти и необходимость сохранения порядка узлов. Методы, обсуждаемые в этой статье, предлагают различные компромиссы, что позволяет вам выбрать наиболее подходящий для вашего конкретного случая использования.