Intuition
Flip one arrow at a time. You need three references each step so the rest of the list is never lost: the already-reversed part (prev), the node being flipped (curr), and the saved next node (nxt).
Approach
Copying values out is wasteful
You could read all values into an array, reverse it, and rebuild the list — but that's O(n) extra space for something that's really just pointer rewiring. The list already holds all the nodes; we only need to flip the direction of each next link, in place.
Reverse one link at a time, but save the tail first
The core move is curr.next = prev — point the current node backward at the portion we've already reversed. The catch: the instant you overwrite curr.next, you lose your only handle on the rest of the list. So before rewiring, save nxt = curr.next. With three references — prev (reversed part), curr (node being flipped), nxt (unprocessed remainder) — no node is ever orphaned.
Slide the trio forward until the end
Each iteration: save nxt, flip curr.next to prev, then advance prev = curr and curr = nxt. Repeat until curr is null. At that point prev sits on what used to be the tail — the new head — so return it. Empty and single-node lists fall out naturally. One pass, O(n) time, O(1) space.
Solution & live demo
Edge cases
curr is null from the start; the loop is skipped and prev (null) is returned.
One iteration flips its next to null and prev becomes that node — the unchanged head.
Saving nxt before rewiring guarantees the unprocessed remainder is always reachable.