You have three segments. The prefix — a single node, [1], still pointing at node 2 through its original .next pointer. The reversed sublist — [4, 3, 2], with arrows flowing backward, node 2's .next pointing at node 3 instead of forward to node 5. And the suffix — [5, 6], intact but disconnected from everything before it.
The reversal loop did its job. Every arrow in positions 2 through 4 now points the right direction. But the loop does not know about boundaries. It flipped arrows inside the zone and left the connections at the edges dangling. Two wires are cut: the wire from the prefix to the reversed sublist (node 1 still points at node 2, which is now the tail, not the head), and the wire from the reversed sublist to the suffix (node 2 no longer points at node 5 — its .next was overwritten to point backward at node 3).
Stitching is the act of rewriting those two wires. It requires exactly two pointer assignments. Not three. Not one. Two. Each assignment reconnects one boundary of the reversed sublist to the surrounding list.
The first wire: connection.next = prev. Before the reversal, connection (node 1) pointed at node 2 — the old head of the sublist. After reversal, the new head is node 4 (held in prev after the loop). So connection.next must be updated from node 2 to node 4. One assignment. The prefix now leads directly into the reversed sublist's new front.
The second wire: tail.next = curr. Before the reversal, you saved tail as a reference to node 2 — the first node that entered the reversal zone. After the loop, node 2 is the last node of the reversed sublist (its .next was overwritten to point at node 3). But node 2 must now point forward to node 5 — the first node in the suffix. That value lives in curr after the loop ends. So tail.next = curr bridges the reversed sublist's end to the suffix.
The beauty of this design is that every variable you need was saved before the reversal loop. connection was captured during the walk. tail was captured immediately after. prev and curr are the natural products of the loop. No additional traversal is required. No re-scanning the list to find the attachment points. The stitch is two lines because the setup was correct.
The danger is miswiring. Point connection.next at the wrong node and you skip the reversed sublist entirely — or create a cycle. Point tail.next at the wrong node and you orphan the suffix — or loop back into the reversed sublist and create an infinite traversal. Both mistakes are invisible at write-time and catastrophic at runtime. A linked list with a cycle will hang any traversal that checks for null termination. The program does not crash — it just never finishes.
connection.next = prev (node 4) and tail.next = curr (node 5). The chain is linear, every node reachable.
A quick aside on why this is iterative, not recursive. A recursive reversal of a sublist would bury the stitching assignments inside the unwind: each frame would need to know its position relative to left and right to decide whether to flip a pointer or leave it alone. That works, but the bookkeeping lives on the call stack instead of in named variables. The iterative version pulls the four anchor points — connection, tail, prev, curr — into plain locals. You can print them, inspect them, reason about them in two lines. Stitching, in particular, collapses to two assignments you can read left-to-right. That legibility is the whole reason this pattern scales from LC 92 to LC 25 to LC 24 without collapsing under its own weight.
Notice: the reversal loop itself is pure — it doesn't know about connection or tail. All boundary awareness lives in the walk before and the stitch after. Separating motion from reconnection is the whole trick.
Below, you will work with the three-segment state from the previous screen. Your job: identify all four anchor points, wire the two connections, and reconstruct the chain.
Three segments. The reversal worked, but the chain is broken. Four specific pointer assignments will reconnect everything. Before writing those assignments, you need to identify the four anchor points.
The stitching pattern you just performed — connection.next = prev, tail.next = curr — appears in every linked list problem that modifies a substructure and needs to reconnect it. Sublist reversal is the canonical case, but the same two-wire pattern shows up when you remove a section, insert a section, or rearrange nodes within a section.
Think of it as a protocol for in-place surgery on a singly-linked list. The protocol has four steps, always in this order:
connection.tail before the modification begins.prev for reversal) and the first node after the zone (held in curr).connection.next = newFront and tail.next = afterZone. These two writes reconnect the modified zone to the surrounding list.Advance a pointer past m-1 nodes. Park at the last node before the zone.
The reason this protocol works is that it decouples the modification from the reconnection. The reversal loop does not need to know about connection or tail. It runs the same save-sever-advance rhythm regardless. All boundary awareness is concentrated in the walk (step 1), the saves (step 2), and the stitch (step 4). The loop (step 3) is a pure, self-contained operation.
This decoupling is what makes the jump from LC 206 (Reverse Linked List) to LC 92 (Reverse Linked List II) feel manageable instead of overwhelming. The core algorithm does not change. The wrapper around it — walk, save, stitch — is new bookkeeping, but it follows a rigid pattern. Once you internalize the four-step protocol, applying it to bounded modifications is systematic, not creative.
connection.next = prev // wire 1: prefix -> new headtail.next = curr // wire 2: old head (now tail) -> suffixTwo lines. Four variables. Zero ambiguity — as long as you saved connection and tail before the loop and you know what prev and curr hold after it.
Flip a sublist, reconnect both ends. Two wires.
connection.next = newHead, tail.next = afterZone
The dummy-node idiom fixes the left = 1 edge case. If the reversal starts at the first node of the list, there is no node before the zone — connection has nowhere to sit. Worse, the return value changes: when left > 1, the original head is still the head of the list; when left = 1, the original head becomes the tail of the reversed zone, and the new head is whatever prev ends up pointing at. Two code paths. Two chances to get it wrong.
The dummy node absorbs both cases. Construct a sentinel before the loop — const dummy = new ListNode(0, head) — and start connection = dummy. Walk it forward left - 1 steps. For left = 1, the walk takes zero steps and connection stays at the dummy. For left > 1, connection advances to the real node before the zone. Either way, the same two stitching assignments work. The return statement becomes return dummy.next: when left = 1, this returns the new head of the reversed segment; when left > 1, it returns the original head, untouched. One code path. One chance to get it right.
A worked example to cement the idiom. Take the list [1, 2, 3, 4, 5] with left = 1, right = 3. Build dummy -> 1 -> 2 -> 3 -> 4 -> 5. Set connection = dummy, walk it forward zero steps (since left - 1 = 0), so it stays at the dummy. Save tail = connection.next, which is node 1. Run the reversal loop for right - left + 1 = 3 steps — this reverses 1 -> 2 -> 3 into 3 -> 2 -> 1, leaving prev at node 3 and curr at node 4. Now stitch: connection.next = prev writes dummy.next = 3; tail.next = curr writes 1.next = 4. The list is now dummy -> 3 -> 2 -> 1 -> 4 -> 5. Return dummy.next, which is node 3 — the new head. If you had returned the original head, you would have returned node 1, pointing the caller at the tail of the reversed zone. The dummy saves the day without a single conditional.
When this fails. The most common failure mode is forgetting to save tail before the reversal loop. By the time the loop exits, the original first node of the zone has had its next pointer rewritten — it now points backward into what used to come before it. If you try to reach it through connection.next after the loop, you'll hit the new head of the reversed segment instead. If you try to recompute it by walking, you'll walk the reversed zone in the wrong direction. The fix is to capture the reference before any mutation begins: tail = connection.next on the line before the loop starts. Second-most-common failure is reading prev as “the previous node we visited” instead of “the new head of the reversed segment.” After a reversal loop, prev is not a historical pointer — it is a named result. Treat it like a return value.
The k-group generalization lives one screen away: LC 25 asks you to reverse every group of k nodes along the list, stitching each reversed group back into the chain before starting the next. The protocol is identical — walk, save, reverse, stitch — but runs in a loop, with connection and tail advancing to the boundary of the next group after each stitch. LC 24 is the degenerate case: k = 2, reverse adjacent pairs. Same protocol, same two wires, same dummy-node return. What changes is how often the protocol fires and where the remainder (trailing group smaller than k) is left untouched.
That is the next screen: the k-group generalization. Same invariant, same protocol, applied repeatedly until the list is exhausted.