The problem. Given the head of a linked list, rotate it to the right by k places: the last k nodes move, in order, to the front. Return the new head. k can be much larger than the length of the list.
[1, 2, 3, 4, 5], k = 2 -> [4, 5, 1, 2, 3]
[0, 1, 2], k = 4 -> [2, 0, 1] (4 mod 3 = 1)
[1, 2, 3], k = 3 -> [1, 2, 3] (a full turn)Rotating by k doesn't change which node follows which — only where the list starts and ends. If you join the tail back to the head, the list becomes a circular list, and every rotation of it is the same ring cut open at a different point. So: count the nodes, close the ring, walk to the node that should be the new tail, and cut.
Two details make it work for any k. Rotating by n (the length) changes nothing, so only k mod n matters — that's what keeps a k of two billion fast. And the new tail is the node n − k − 1 steps from the old head, because the last k nodes come before it.
function rotateRight(head, k) { if (head === null || head.next === null) return head; let n = 0; for (let curr = head; curr !== null; curr = curr.next) n++; for (let r = 0; r < k % n; r++) { // rotate by one, k mod n times let beforeTail = head; while (beforeTail.next.next !== null) beforeTail = beforeTail.next; const tail = beforeTail.next; beforeTail.next = null; // detach the last node... tail.next = head; // ...and put it in front head = tail; } return head;}Time O(n · (k mod n)) — up to O(n²), space O(1). Each single rotation walks the whole list to find the node before the tail. Without the k % n, a huge k would never finish.
Count and find the tail, join it to the head, walk n − k − 1 steps, cut.
function rotateRight(head, k) { if (head === null || head.next === null) return head; let n = 1, tail = head; while (tail.next !== null) { // count the nodes and find the tail tail = tail.next; n++; } k %= n; // rotating by n changes nothing if (k === 0) return head; tail.next = head; // close the list into a ring let newTail = head; for (let i = 0; i < n - k - 1; i++) newTail = newTail.next; // n - k - 1 steps from the head const newHead = newTail.next; newTail.next = null; // cut the ring after the new tail return newHead;}Time O(n), space O(1). One full walk to count and find the tail, then at most one more partial walk to the cut. Making the list circular for a moment turns move k nodes from the back to the front into choose where the ring opens.
[0, 1, 2] with k = 4 is the same as k = 1.