← Назад к вопросам
Сложение двух связных списков
2.2 Middle🔥 201 комментариев
#Теория тестирования
Условие
Даны два связных списка, представляющих два неотрицательных числа. Цифры хранятся в обратном порядке. Сложите эти два числа и верните результат в виде связного списка.
Пример
Вход: 2->4->3 (342), 5->6->4 (465) Выход: 7->0->8 (807)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение: Сложение двух связных списков
Эта задача требует работы со связными списками. Ключевой момент — цифры хранятся в обратном порядке, что упрощает сложение (начинаем с младших разрядов).
Алгоритм решения
- Создаём новый связный список для результата
- Инициализируем переменную переноса (carry) = 0
- Проходим по обоим спискам одновременно:
- Берём значение из первого списка (или 0, если список закончился)
- Берём значение из второго списка (или 0, если список закончился)
- Складываем оба значения + carry из предыдущей итерации
- Новая цифра = сумма % 10
- Новый carry = сумма // 10
- Добавляем новый узел в результирующий список
- Если после окончания списков остался carry — добавляем его в результат
- Возвращаем результирующий список
Структура узла списка
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
Реализация решения
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def addTwoNumbers(l1: ListNode, l2: ListNode) -> ListNode:
# Создаём фиктивный узел для упрощения логики
dummy_head = ListNode(0)
current = dummy_head
carry = 0
# Проходим по обоим спискам
while l1 or l2 or carry:
# Получаем значения из узлов (если они существуют)
val1 = l1.val if l1 else 0
val2 = l2.val if l2 else 0
# Суммируем значения и перенос
total = val1 + val2 + carry
# Вычисляем новую цифру и перенос
carry = total // 10
digit = total % 10
# Создаём новый узел и добавляем в результат
current.next = ListNode(digit)
current = current.next
# Переходим к следующим узлам (если они существуют)
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
return dummy_head.next
Пошаговый разбор примера
Вход: 2->4->3 (342), 5->6->4 (465)
Итерация 1:
- val1 = 2, val2 = 5, carry = 0
- total = 2 + 5 + 0 = 7
- digit = 7, carry = 0
- result: 7
Итерация 2:
- val1 = 4, val2 = 6, carry = 0
- total = 4 + 6 + 0 = 10
- digit = 0, carry = 1
- result: 7->0
Итерация 3:
- val1 = 3, val2 = 4, carry = 1
- total = 3 + 4 + 1 = 8
- digit = 8, carry = 0
- result: 7->0->8
Итерация 4:
- l1 = None, l2 = None, carry = 0 → выход из цикла
Выход: 7->0->8 (807) ✓
Вспомогательные функции для тестирования
def create_list(digits: list) -> ListNode:
"""Создаёт связный список из массива цифр"""
if not digits:
return None
head = ListNode(digits[0])
current = head
for digit in digits[1:]:
current.next = ListNode(digit)
current = current.next
return head
def list_to_array(node: ListNode) -> list:
"""Преобразует связный список в массив"""
result = []
while node:
result.append(node.val)
node = node.next
return result
# Тесты
l1 = create_list([2, 4, 3])
l2 = create_list([5, 6, 4])
result = addTwoNumbers(l1, l2)
print(list_to_array(result)) # [7, 0, 8]
Сложность
- Временная сложность: O(max(m, n)), где m и n — длины списков
- Пространственная сложность: O(max(m, n)) для создания нового списка
Особенности решения
- Фиктивный узел упрощает логику — не нужно проверять, существует ли head результата
- Обработка переноса правильно работает для всех случаев, включая последний перенос
- Универсальность — решение работает для списков разной длины
Решение имеет оптимальную сложность и корректно обрабатывает все граничные случаи.