Leetcode.com, задача №206. "Переворот связного списка".
!!НАШ БЛОГ ПЕРЕЕХАЛ!!
Мы создали свой сайт! Все материалы, опубликованные в этом блоге, переехали туда.
Наш новый сайт maddevelop.ru
А данную статью вы можете найти по ссылке
Условие
Отобразите в обратном направлении простой связный список.
Пример
Входной список: 1 -> 2 -> 3 -> 4 -> 5 -> null
Выходной список: 5 -> 4 -> 3 -> 2 -> 1 -> null
Итеративный вариант решения
Немного теории.
Связный список — базовая динамическая структура данных в информатике, состоящая из узлов, каждый из которых содержит как собственно данные, так и одну или две ссылки («связки») на следующий и/или предыдущий узел списка.
В нашем случае мы имеем дело с простым связным списком, т.е. каждый узел содержит ссылку на один последующий:
public class ListNode
{
public int val; // поле, хранящее значение начала списка
public ListNode next; // поле, указывающее на всю последующую часть
public ListNode(int x) { val = x; } // конструктор
}
Создать входной связный список из примера можно, например, так:
ListNode ssp = new ListNode(1); ssp.next = new ListNode(2); ssp.next.next = new ListNode(3); ssp.next.next.next = new ListNode(4); ssp.next.next.next.next = new ListNode(5); ssp.next.next.next.next.next = null;
Итеративный подход (англ. iteration - «повторение») в разработке программного обеспечения — это выполнение работ параллельно с непрерывным анализом полученных результатов и корректировкой предыдущих этапов работы.
Код метода реверса связного списка:
public static ListNode ReverseList(ListNode head)
{
ListNode prev = null;
ListNode curr = head;
while (curr != null)
{
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
До тех пор, пока не достигнем окончания списка мы на каждой итерации будем выполнять четыре операции:
- Запоминать ссылку на следующий узел.
ListNode nextTemp = curr.next;
- В текущем списке ссылку на следующий узел заменять на скорректированную.
curr.next = prev;
- Запоминать текущее состояние списка.
prev = curr;
- Переходить к следующему узлу.
curr = nextTemp;
Посмотрим, как работает алгоритм для связного списка 1 -> 2 -> 3 -> null.
Итерация №1
nextTemp = curr.next = 2 -> 3 -> null curr.next = prev = null prev = curr = 1 -> null curr = 2 -> 3 -> null
Итерация №2
nextTemp = curr.next = 3 -> null curr.next = prev = 1 -> null prev = curr = 2 -> 1 -> null curr = 3 -> null
Итерация №3
nextTemp = curr.next = null curr.next = prev = 2 -> 1 -> null prev = curr = 3 -> 2 -> 1 -> null curr = null
Т.к. curr = = null, то произойдёт выход из цикла.
Временная сложность: n, т.к. количество итераций зависит от количества узлов списка.
Пространственная сложность: 1, т.к. мы используем лишь дополнительные переменные, кроме основного других циклов нет.
Рекурсивный вариант решения
Код решения с рекурсией выглядит таким образом:
public static ListNode ReverseList(ListNode head)
{
if (head == null || head.next == null)
retutn head;
ListNode p = ReverseList(head.next);
head.next.next = head;
return p;
}
Рассмотрим действие алгоритма на примере списка 1 -> 2 -> 3 -> null.
Первый (основной) вызов метода
ReverseList(1 -> 2 -> 3 -> null)
{
ListNode p = ReverseList(2 -> 3 -> null)
Происходит второй вызов метода.
ListNode p = ReverseList(3 -> null);
Происходит третий вызов метода.
Третий вызов возвращает 3 -> null, т.к. head.next == null.
Получаем, что ListNode p = 3 -> null.
В начале второго вызова head = 2 -> 3 -> null.
head.next.next = head
Получаем, что head = 2 -> 3 -> 2 -> 3 -> null.
При этом p = 3 -> 2 -> 3 -> null
head.next = null
Таким образом, head = 2 -> null, a p = 3 -> 2 -> null.
Второй вызов возвращает 3 -> 2 -> null.
При возврате к первому методу head = head -> head.next = 1 -> 2 -> null
ListNode p = 3 -> 2 -> null.
head.next.next = head = 1 -> 2 -> 1 -> 2 -> null
При этом p = 3 -> 2 -> 1 -> 2 -> 1 -> 2 -> null
head.next = null = 1 -> null
p, оно же и ответ, становится равным 3 -> 2 -> 1 -> null
}
Временная сложность: n, по-прежнему зависит от длины списка.
Пространственная сложность: n, т.к. равняется глубине рекурсии.
Ещё больше интересной информации на нашем Telegram канале.