Перейти к содержимому

206. Reverse Linked List

Лёгкая
Паттерн:
in-place pointer reversal
Время:
O(n)
Память:
O(1)
Написано:

Заметки написаны на английском.

Задача

Reverse a singly linked list and return the new head.

1 -> 2 -> 3 -> 4 -> null      (before)
null <- 1 <- 2 <- 3 <- 4      (after — head is now 4)

Подход

The whole problem is just: don't let go of a hand before you know who you're grabbing next.

Kids in a line holding hands, pointing forward. I flip each kid's hand to point backward, one at a time, using two "fingers" (prev, curr) and one sticky note (nextTemp) so I never lose the rest of the list mid-flip.

Решение

public ListNode reverseList(ListNode head) {
    ListNode prev = null;
    ListNode curr = head;

    while (curr != null) {
        ListNode nextTemp = curr.next; // 1. save next BEFORE overwriting
        curr.next = prev;              // 2. flip the arrow
        prev = curr;                   // 3. prev catches up to curr
        curr = nextTemp;               // 4. curr moves to the saved node
    }

    return prev; // when curr hits null, prev is the new head
}

Recursive version (kept for reference, not submission)

public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) return head;

    ListNode newHead = reverseList(head.next);
    head.next.next = head;  // the node after head now points back to head
    head.next = null;       // head becomes the tail, so it points to nothing

    return newHead;
}

Tricky part here: head.next.next = head only makes sense once you accept that head.next is still the last node of the already-reversed sublist at that point in the call — it hasn't been touched yet by this frame.

Ошибки

I could read the code fine, but I didn't believe it until I traced it by hand.

Выводы

The one line order that actually matters

nextTemp = curr.next must happen before curr.next = prev.

If I flip the arrow first, I overwrite the only reference I had to the rest of the list — it just becomes unreachable garbage. This is the classic "gotcha," and it's basically the same lesson as x = x++ on the OCA exam: statement order changes the outcome when you're reading and writing the same variable in one step.

Why iterative and not recursion by default

  • Iterative: 3 reference variables total, no matter how long the list is. Safe.
  • Recursive: elegant, but every node = one stack frame. Long list on LeetCode → StackOverflowError. That's a real Error subclass from OCA material, not something you're meant to catch and recover from — it means "this approach doesn't scale," full stop.

Takeaway for myself: default to iterative for linked list problems unless told otherwise. Recursion is nice to show I understand it, not what I submit.

Java 8

No streams, no var, no lambdas — just while, references, and object creation. Fully valid on Java 8 and honestly on Java 1.0 too.

Время и память

IterativeRecursive
TimeO(n)O(n)
SpaceO(1)O(n) — call stack

Проверить себя

  • Can I write the iterative version from memory without looking?
  • Can I explain out loud why nextTemp has to come first, without the kids-holding-hands analogy as a crutch?
  • What breaks if I return curr instead of prev at the end? (Answer: curr is null by the time the loop exits — that's the whole reason we needed prev in the first place.)