Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Reverse Linked List
DSA

Reverse Linked List

Linked list reversal — full reverse, sublist reverse between m and n, and K-group reversal, in C++, Python, Java and JavaScript.

Reversal rewires each node’s next to point backward — three pointers do it in one pass.

Focus on recognizing:

“Reverse” / “reverse part of a list” → prev / cur / next dance


Pattern 1: Reverse the Entire List

Watch 1→2→3→4 rewire node by node — arrows flip, prev ends up as the new head. Press to animate.

Reverse A Linked List

Reverse a singly linked list — compare the iterative prev/cur/next dance with the recursive unwind.

At each node save cur.next, point cur.next at prev, then advance prev and cur. When cur is null, prev is the new head. One pass, O(1) space.

LINKED LIST VISUALIZER
Steps
1234
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        prev = null; cur = head
                      
                        2
                        while cur:
                      
                        3
                          next = cur.next   // save the rest
                      
                        4
                          cur.next = prev   // flip the arrow
                      
                        5
                          prev = cur; cur = next
                      
                        6
                        return prev          // new head
                      
public ListNode reverseList(ListNode head) {
    ListNode prev = null, cur = head;

    while (cur != null) {
        ListNode next = cur.next; // save
        cur.next = prev;          // flip arrow
        prev = cur;               // advance
        cur = next;
    }

    return prev;                  // new head
}
def reverse_list(head):
    prev, cur = None, head

    while cur:
        cur.next, prev, cur = prev, cur, cur.next

    return prev                   # new head
ListNode* reverseList(ListNode* head) {
    ListNode *prev = nullptr, *cur = head;

    while (cur) {
        ListNode* next = cur->next; // save
        cur->next = prev;           // flip arrow
        prev = cur;
        cur = next;
    }

    return prev;                    // new head
}
function reverseList(head) {
  let prev = null,
    cur = head;

  while (cur) {
    const next = cur.next; // save
    cur.next = prev; // flip arrow
    prev = cur;
    cur = next;
  }

  return prev; // new head
}

Save next BEFORE flipping — otherwise the rest of the list is unreachable.


Pattern 2: Reverse Sublist [left, right]

Anchor before the window, then pull each node to the front of it. Press to animate.

Reverse Linked List II (Sublist)

Reverse the nodes of a linked list from position left to right, inclusive.

Park a pointer just before left, then repeatedly move the next node to the front of the window — the 'move next behind prev' shuffle — and finally reseam the tail. One pass, O(1) extra space.

LINKED LIST VISUALIZER
Steps
12345
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        advance prev to node before left
                      
                        2
                        for r-l times:
                      
                        3
                          move cur.next behind prev
                      
                        4
                        reconnect tail
                      

Anchor a node before left, then insert-reverse right − left + 1 nodes:

public ListNode reverseBetween(ListNode head, int left, int right) {
    ListNode dummy = new ListNode(0, head);
    ListNode before = dummy;

    for (int i = 1; i < left; i++)
        before = before.next;          // node before sublist

    ListNode prev = before.next, cur = prev.next;

    for (int i = 0; i < right - left; i++) {
        ListNode next = cur.next;
        cur.next = prev;               // flip
        prev = cur;
        cur = next;
    }

    before.next.next = cur;            // tail of sublist
    before.next = prev;                // head of sublist

    return dummy.next;
}
def reverse_between(head, left, right):
    dummy = ListNode(0, head)
    before = dummy

    for _ in range(left - 1):
        before = before.next       # node before sublist

    prev, cur = before.next, before.next.next

    for _ in range(right - left):
        nxt = cur.next
        cur.next = prev            # flip
        prev, cur = cur, nxt

    before.next.next = cur         # tail of sublist
    before.next = prev             # head of sublist

    return dummy.next
ListNode* reverseBetween(ListNode* head, int left, int right) {
    ListNode dummy(0, head);
    ListNode* before = &dummy;

    for (int i = 1; i < left; i++)
        before = before->next;       // node before sublist

    ListNode *prev = before->next, *cur = prev->next;

    for (int i = 0; i < right - left; i++) {
        ListNode* next = cur->next;
        cur->next = prev;            // flip
        prev = cur;
        cur = next;
    }

    before->next->next = cur;        // tail of sublist
    before->next = prev;             // head of sublist

    return dummy.next;
}
function reverseBetween(head, left, right) {
  const dummy = new ListNode(0, head);
  let before = dummy;

  for (let i = 1; i < left; i++) before = before.next;

  let prev = before.next,
    cur = prev.next;

  for (let i = 0; i < right - left; i++) {
    const next = cur.next;
    cur.next = prev; // flip
    prev = cur;
    cur = next;
  }

  before.next.next = cur; // tail of sublist
  before.next = prev; // head of sublist

  return dummy.next;
}

The dummy node means “reverse starting at index 1” needs no special case.


Pattern 3: Reverse Nodes in K-Group

Probe k ahead first; partial groups stay untouched. Press to animate.

Reverse Nodes In K-Group

Reverse nodes of a linked list in groups of k; leave any partial trailing group as-is.

Probe k nodes ahead; if a full group exists, reverse it in place and stitch it to the previous group's tail, then recurse from the new group tail. A leftover group shorter than k is appended unchanged.

LINKED LIST VISUALIZER
Steps
12345
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        probe k nodes ahead — enough left?
                      
                        2
                        no  → append rest, stop
                      
                        3
                        yes → reverse this group
                      
                        4
                        prevGroup.next = new head
                      
                        5
                        recurse from group tail
                      

Reverse k at a time; leave the tail partial group untouched:

public ListNode reverseKGroup(ListNode head, int k) {
    // check there are k nodes left
    ListNode node = head;
    for (int i = 0; i < k; i++) {
        if (node == null) return head;   // not enough
        node = node.next;
    }

    // reverse exactly k
    ListNode prev = null, cur = head;
    for (int i = 0; i < k; i++) {
        ListNode next = cur.next;
        cur.next = prev;
        prev = cur;
        cur = next;
    }

    head.next = reverseKGroup(cur, k);   // recurse on the rest
    return prev;
}
def reverse_k_group(head, k):
    # check there are k nodes left
    node = head
    for _ in range(k):
        if not node:
            return head          # not enough
        node = node.next

    # reverse exactly k
    prev, cur = None, head
    for _ in range(k):
        cur.next, prev, cur = prev, cur, cur.next

    head.next = reverse_k_group(cur, k)  # recurse on the rest
    return prev
ListNode* reverseKGroup(ListNode* head, int k) {
    // check there are k nodes left
    ListNode* node = head;
    for (int i = 0; i < k; i++) {
        if (!node) return head;      // not enough
        node = node->next;
    }

    // reverse exactly k
    ListNode *prev = nullptr, *cur = head;
    for (int i = 0; i < k; i++) {
        ListNode* next = cur->next;
        cur->next = prev;
        prev = cur;
        cur = next;
    }

    head->next = reverseKGroup(cur, k); // recurse on the rest
    return prev;
}
function reverseKGroup(head, k) {
  // check there are k nodes left
  let node = head;
  for (let i = 0; i < k; i++) {
    if (!node) return head; // not enough
    node = node.next;
  }

  // reverse exactly k
  let prev = null,
    cur = head;
  for (let i = 0; i < k; i++) {
    const next = cur.next;
    cur.next = prev;
    prev = cur;
    cur = next;
  }

  head.next = reverseKGroup(cur, k); // recurse on the rest
  return prev;
}

Pre-check k availability first — reversing then discovering you can’t finish leaves a mess.


Common Mistakes

Flipping before saving next.

The remainder of the list is lost forever.


Forgetting to reconnect the reversed sublist.

Sublist reversal must stitch both ends back: before.next = newHead and subTail.next = after.


Returning head after full reversal.

Return prev — the original head is now the LAST node.


Complexity

OperationTimeSpace
Full reverseO(n)O(1)
SublistO(n)O(1)
K-groupO(n)O(n/k) recursion

My Private Notes

Notes are auto-saved locally to this device.