Rotate List
Given the head of a linked list, rotate it to the right by k places and return the new head. Rotating right by 1 moves the last node to the front; rotating by k moves the last k nodes to the front as a block, preserving their order. k can be far larger than the list length. Rewire in place. An empty or single-node list, and any k that is a multiple of the length, returns the list unchanged.
- The number of nodes is in the range [0, 500]
- -100 <= Node.val <= 100
- 0 <= k <= 2 × 10⁹
head = [1,2,3,4,5], k = 2[4,5,1,2,3]head = [0,1,2], k = 4[2,0,1]head = [1,2,3], k = 3[1,2,3]Rotating right by k means the last k nodes swing around to the front as a block, order preserved: [1,2,3,4,5] rotated by 2 becomes [4,5,1,2,3]. Nothing about the values changes — we are only choosing a new starting point and cutting the list there.
The literal reading: rotate by one, k times. Each single rotation walks to the last node, moves it to the front, and repeats. That is O(N) per rotation, so O(k × N) overall — and k can be 2 × 10⁹, astronomically larger than the at-most-500 nodes. Almost all of that work is redundant: rotating a length-L list by L returns it to the start, so only k mod L rotations actually matter. Doing k of them is repeating the same cycle billions of times.
Rotation is not really about moving k nodes — it is about choosing where the list begins. Connect the tail back to the head and the list becomes a ring with no start and no end. On a ring, every node is a potential head; rotating is just deciding which one, then snapping the single link behind it to reopen the ring into a line. So instead of k moves we do exactly one cut — the whole cost of k collapses into finding the right place to snap.
Reduce first: k %= length, because rotating by a full length changes nothing. To bring the last k nodes to the front, the new tail must be the node just before that block — the node at index length - k - 1 counting from the head (index 0). Its successor becomes the new head. We manage three roles: a scout that finds the old tail (and measures length on the way), the new tail (the breakpoint), and the new head.
if not head or not head.next or k == 0:
return head
# 1. Measure length and reach the old tail
curr, length = head, 1
while curr.next:
curr = curr.next
length += 1
curr.next = head # close the ring: old tail -> old head
# 2. Reduce k and locate the new tail
k %= length
steps_to_new_tail = length - k - 1
new_tail = head
for _ in range(steps_to_new_tail):
new_tail = new_tail.next
# 3. Snap the ring open behind the new head
new_head = new_tail.next
new_tail.next = None
return new_headk %= length before computing the cut, and only after you know the length. If k is a multiple of the length, k % length is 0, steps_to_new_tail is length - 1, the new tail is the old tail, and we snap exactly where the list already ended — returning it unchanged, which is correct. Skip the reduction and length - k - 1 goes wildly negative for large k, and the walk to the new tail is meaningless. Also note we must close the ring before cutting: it's what lets the last k nodes lead into the old head seamlessly.One pass to measure, part of another to reach the cut: O(N) time, O(1) space — independent of k entirely, because k was reduced modulo the length. The reflex worth keeping: when an operation repeats a cyclic action k times and k can be huge, the answer is almost never "do it k times" — reduce k modulo the cycle length, or reframe the repetition as a single structural change (here, ring-and-cut). The same "wrap into a ring, snap once" idea reappears whenever rotation meets a circular structure.
Ring Persistence Manipulation
Phase Details
Phase 1: Measure & Modulo
Traverse the list to find length N. Compute effective rotation: `k = k % N`. If `k=0`, we stop.
We use k = k % length because rotating a list of length 5 by 7 steps is the same as rotating it by 2 steps.
Time Complexity: O(N) | Space Complexity: O(1). Converting to a circle simplifies complex head/tail shuffling.