← Назад к вопросам

Переворот связного списка

1.6 Junior🔥 201 комментариев
#Python Core

Условие

Переверните односвязный список.

Пример

Вход: 1 → 2 → 3 → 4 → 5 Выход: 5 → 4 → 3 → 2 → 1

Определение узла

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

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Переворот связного списка

Переворот связного списка — одна из классических задач, проверяющих понимание работы с указателями и манипуляцией структурами данных. Решение требует изменения направления связей между узлами.

Подход 1: Итеративное решение (Iterative Reversal)

Итеративный подход — самый эффективный и наиболее часто используемый в production коде. Идея простая: мы проходим по списку и переворачиваем стрелки (связи) между узлами.

Алгоритм:

  • Используем три указателя: prev, current и next
  • На каждом шаге сохраняем следующий узел
  • Переворачиваем стрелку текущего узла на предыдущий
  • Двигаемся дальше по списку
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverseList(head):
    prev = None
    current = head
    
    while current:
        # Сохраняем следующий узел
        next_node = current.next
        
        # Переворачиваем связь
        current.next = prev
        
        # Двигаемся дальше
        prev = current
        current = next_node
    
    return prev

Сложность:

  • Временная сложность: O(n) — один проход по списку
  • Пространственная сложность: O(1) — используем только несколько переменных

Подход 2: Рекурсивное решение

Рекурсивный подход более элегантен, но требует дополнительную память на стек вызовов.

def reverseListRecursive(head):
    # Базовый случай: пустой список или один узел
    if not head or not head.next:
        return head
    
    # Рекурсивно переворачиваем оставшуюся часть
    new_head = reverseListRecursive(head.next)
    
    # Переворачиваем текущую связь
    head.next.next = head
    head.next = None
    
    return new_head

Сложность:

  • Временная сложность: O(n)
  • Пространственная сложность: O(n) — из-за стека вызовов

Пример использования

# Создаём список: 1 → 2 → 3 → 4 → 5
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)
head.next.next.next.next = ListNode(5)

# Переворачиваем
reversed_head = reverseList(head)

# Проверяем результат
current = reversed_head
while current:
    print(current.val, end=" -> ")
    current = current.next
print("None")
# Вывод: 5 -> 4 -> 3 -> 2 -> 1 -> None

Когда какой подход использовать

Используй итеративное решение когда:

  • Нужна максимальная производительность
  • Важна пространственная сложность O(1)
  • Работаешь с очень большими списками

Используй рекурсивное решение когда:

  • Код должен быть максимально читаемым
  • Размер входных данных небольшой
  • Готов к overhead памяти на стек

Практические применения

Переворот списков используется в:

  • Проверке палиндромов в связных списках
  • Обращении очередей в некоторых алгоритмах
  • Преобразовании структур данных перед сортировкой
  • Обработке потоков данных в реальном времени

Типичные ошибки

Потеря ссылки на следующий узел — обязательно сохрани его в переменную перед изменением

Забывают установить head.next = None в рекурсивном решении

Off-by-one ошибки в условии цикла