You are given the head of a singly linked list and an integer k. Reverse the nodes of the list k at a time and return the head of the modified list.
Walk the list from the front and split it into consecutive blocks of k nodes. Reverse the order of nodes within each block, while keeping the blocks themselves in their original left-to-right order.
If the number of nodes is not a multiple of k, the left-out nodes at the end form a final block that must also be reversed.
Only the links between nodes change — you should not need to allocate any new nodes.
Input: head = [1,2,3,4,5,6], k = 2 Output: [2,1,4,3,6,5] Each block of 2 nodes is reversed: (1,2) -> (2,1), (3,4) -> (4,3), (5,6) -> (6,5).
Input: head = [1,2,3,4,5,6], k = 4 Output: [4,3,2,1,6,5] The first block of 4 is reversed to 4,3,2,1; the leftover block (5,6) is reversed to 6,5.
- 1 <= size of the linked list <= 10^5 - 0 <= node value <= 10^6 - 1 <= k <= size of the linked list
Reversing a whole linked list is a rite of passage. This problem asks for something sharper: reverse the list in bite-sized blocks of k, then re-link the blocks so nothing is lost. Master the stitch and you own a whole family of linked-list problems.
k steps at a time.next fields without losing the rest of the list.In plain English: break the list into consecutive chunks of k nodes (the last chunk may be shorter), reverse the order of nodes inside each chunk, and keep the chunks in their original sequence. Return the new head.
Formally: given head and integer k, produce a list where nodes [0, k) are reversed, then [k, 2k), and so on — including a final, possibly shorter, block.
Worked example — head = 1 → 2 → 3 → 4 → 5, k = 2
group [1,2] → 2 → 1 group [3,4] → 4 → 3 group [5] → 5 (leftover — still a group; reversing a lone node is a no-op) result: 2 → 1 → 4 → 3 → 5
Asking before coding shows you probe the contract instead of assuming it.
“If the node count is not a multiple of k, is the final partial group reversed or left as-is?”
This flips the whole solution: here the leftover block is reversed, unlike the stricter variant that leaves the tail untouched.
“Is k guaranteed to be at least 1?”
A k of 0 would be undefined; confirming the lower bound lets you skip a guard or add one deliberately.
“Can k be larger than the list length?”
If so, the entire list is a single group and is fully reversed.
“How large can the list get?”
Up to 1e5 nodes rules out anything worse than linear and warns against deep recursion.
Before I code, a few quick checks on the contract.
Most importantly — if the last group is shorter than k, I should still reverse it, correct?
And k is always at least 1, and may exceed the list length, in which case the whole list reverses?
Given up to 1e5 nodes, I'll aim for a single linear pass with constant extra space, done iteratively to avoid stack depth.
The standard reversal walks prev/cur/next until the list ends. Cap that walk at
k steps and you have reversed exactly one group — the same loop, stopped early.
repeat up to k times: next ← cur.next; cur.next ← prev; prev ← cur; cur ← next after: prev = new head of the block, the node you started from = new tail
Before reversing, the first node of a block leads it. After reversing, it trails. That trailing node is exactly where the next reversed block must be welded on — so remember it.
Everything reduces to: capture the first group's new head once (it's the answer), and for every later group, connect the previous group's saved tail to this group's new head. The leftover group needs no special case — the same k-capped loop simply runs out early and reverses whatever remains.
| Brute force (value copy) | Optimal (pointer reversal) | |
|---|---|---|
| Time | O(n) | O(n) |
| Space | O(n) | O(1) |
| Idea | flip values in an array | rewire next pointers |
Both are linear in time; the optimal wins on space by never copying the data. Full code for each is in the Approaches selector below.
Key takeaway
Reverse-in-a-window, then re-stitch: run the classic three-pointer reversal but
cap it at k, track each group's new head and new tail, and weld consecutive
groups together. This one template powers most "operate on groups of a list"
problems.
cur ← head; newHead ← null; prevTail ← null
while cur:
reverse up to k nodes from cur → newGroupHead; groupTail ← old cur; node ← rest
if newHead is null: newHead ← newGroupHead
if prevTail: prevTail.next ← newGroupHead
prevTail ← groupTail; cur ← node
return newHead