Если кому-то все еще интересно, вот решение, которое вообще не использует никаких новых переменных, кроме тех, которые передаются в рекурсивном вызове.
public static List invert(List l) {
invert(l.next, l, l);
l = l.next;
breakCycle(l, l);
return l;
}
private static void invert(List l, List toBeNext, List first) {
if(l.next == null) {
l.next = toBeNext;
first.next = l;
} else {
invert(l.next, l, first);
l.next = toBeNext;
}
}
private static void breakCycle(List l, List first) {
if(l.next == first) {
l.next = null;
} else {
breakCycle(l.next, first);
}
}
Идея состоит в следующем: сначала мы запускаем функцию инвертирования рекурсивнои реализовать его таким образом, чтобы при достижении последнего элемента он назначался следующим элементом текущего заголовка (параметр first
).После того, как мы выполнили его, у нас будет обратный список, но зацикленный, поэтому текущий head.next будет указывать на заголовок обратного списка.Мы переназначаем заголовок на его следующий элемент (фактический заголовок обратного списка), и последнее, что нам нужно сделать, это разорвать цикл.Поэтому мы называем breakCycle
, который выполняет работу рекурсивно!