Skip to content
DSAPrep

    ↑↓ to move · Enter to open · Esc to close

    Reverse Linked List

    Given the head of a singly linked list, reverse the list, and return the reversed list.

    Example 1

    Input: head = [1,2,3,4,5]

    Output: [5,4,3,2,1]

    Example 2

    Input: head = [1,2]

    Output: [2,1]

    Example 3

    Input: head = []

    Output: []

    Constraints

    • The number of nodes in the list is the range [0, 5000].
    • -5000 <= Node.val <= 5000
    Follow-up: A linked list can be reversed either iteratively or recursively. Could you implement both?
    View original on LeetCode ↗

    Rebuild With Extra Space

    Time O(n)Space O(n)

    Read every value into a list, then build a brand new linked list in the opposite order. Simple to reason about, but it allocates an entirely new set of nodes instead of reusing the ones you already have.

    class ListNode:
    def __init__(self, val=0, next=None):
    self.val = val
    self.next = next
    class Solution:
    def reverseList(self, head: ListNode | None) -> ListNode | None:
    values = []
    node = head
    while node:
    values.append(node.val)
    node = node.next
    dummy = ListNode()
    tail = dummy
    for v in reversed(values):
    tail.next = ListNode(v)
    tail = tail.next
    return dummy.next

    Correct, and O(n) time, but the extra O(n) space for the new nodes is unnecessary — every node we need already exists, we just need to point them the other way.

    Iterative In-Place Reversal

    OptimalTime O(n)Space O(1)

    Walk the list once, and at each node flip its next pointer to point backward to the node you came from instead of forward. You need to save curr.next in a temporary variable first, since you’re about to overwrite it and would otherwise lose the rest of the list.

    class Solution:
    def reverseList(self, head: ListNode | None) -> ListNode | None:
    prev = None
    curr = head
    while curr:
    next_node = curr.next # save before overwriting
    curr.next = prev # reverse the pointer
    prev = curr # advance prev
    curr = next_node # advance curr
    return prev

    Watch the three pointers: prev is where a link flips back to, curr is the node being rewired, and next_node preserves the escape route the instant before curr.next is overwritten.

    prevNone
    curr1
    next_node2
    1
    →2
    2
    →3
    3
    →4
    4
    →5
    5
    —
    None
    end
    1 / 6
    currentresultcomparing

    Start: prev=None, curr=head (node 1). Every link points forward. The next_node slot preserves the escape route before each rewire.

    Why it’s correct: every node’s next pointer is redirected exactly once, to the node that preceded it in the original list — after n iterations, every link has been flipped and prev sits on the old tail, which is now the new head. Complexity: single pass, three pointer variables → O(n) time, O(1) space — this is optimal, since producing a reversed list requires touching every node at least once.

    More Linked List practice