2Brute2Best
🔥0

Rotate List

Medium·LeetCode #61Basic Reinforcement
LeetCode
30-Second Mental ModelLinked List — Reordering / rotation (close the circle, cut once)
Complexity:O(n · (k % n))→O(n)
Key Insight

Shifting right by s (where s = k % n) is the same as cutting the list at one place. Count the nodes and find the tail. Join the tail to the head to make a circle. A circle has no start, so cut it once, right after the node that will end the new list. Shifting the circle changes nothing except where you cut it.

Core Validity Invariant

The answer is the circle read from the node n − (k % n) steps from the old head, with the link just before that node cut.

01

Problem

You are given the head of a singly linked list and a number k. Move the list k places to the right. Each shift takes the last node and puts it at the front. Return the new head.

The list is changed by relinking nodes. Do not copy values into new nodes.

Input

head, the first node of a singly linked list (it can be empty), and k, a number that is zero or more.

Output

The head of the rotated list.

Example 1
Input: head = [1, 2, 3, 4, 5], k = 2
Output: [4, 5, 1, 2, 3]

Two shifts: first 5 moves to the front, then 4 does. The last two nodes end up at the front.

Example 2
Input: head = [0, 1, 2], k = 4
Output: [2, 0, 1]

There are only 3 nodes. Three shifts give the same list back, so 4 shifts is the same as 1 shift: 2 moves to the front.

Constraints
  • • The list has between 0 and 500 nodes.
  • • -100 ≤ Node.val ≤ 100
  • • 0 ≤ k ≤ 2 × 10^9
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    If k = 1, which node becomes the new head? What about k = 2?

  2. 2.

    What happens when k is bigger than the number of nodes? Do I really need to shift that many times?

  3. 3.

    Where does the new head sit, counting from the old head? Can I find that spot with one walk?

  4. 4.

    If I join the tail back to the head, what shape does the list have? Where would I cut it?

  5. 5.

    When k is an exact multiple of the length, what should the answer look like?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceRepeat k % n times: walk to the last node and move it to the frontO(n · (k % n))O(1)
OptimalCount n, join the tail to the head, walk n − k%n − 1 steps and cutO(n)O(1)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “rotate the list to the right by k”The tail wraps around to the front → join the tail to the head to make a circle, then cut it.
  • “k can be bigger than the length”A full turn changes nothing → use k % n, never k itself.
  • “singly linked list, return the new head”Only one link changes → relink nodes, no copying of values.
singly linked list+tail joins head (circle)+cut after n − (k mod n) nodes→Linked List — Reordering / rotation (close the circle, cut once)

Reordering here means splitting one list at one point and putting the two parts in swapped order. Rotate List is the simplest reorder: one cut is enough. The join is a helper: it lets the cut land anywhere on the circle. Odd Even Linked List and Reorder List later need several relinks in turn, not just one join and one cut.

10

Don't make this mistake

Forgetting k % n when k is bigger than the list
✗ int steps = n - k; // k = 7, n = 5 gives -2
✓ int steps = n - k % n; // 7 % 5 = 2, so the new head is 3 steps from the old head

k can be far bigger than n, up to 2 × 10^9. A full turn changes nothing, so only k % n matters. Without it, the cut position is negative or past the end, and the answer is wrong or the program crashes.

Walking one node too far when k is a multiple of n
✗ tail->next = head; ListNode* newTail = head; for (int i = 0; i < n - k % n; i++) newTail = newTail->next; // k % n == 0 walks n steps ListNode* newHead = newTail->next; newTail->next = nullptr;
✓ if (k % n == 0) return head; // a full turn changes nothing tail->next = head; // ... then walk n - k % n - 1 steps

When k % n is 0, the loop walks one node too far. newTail lands on the old head, so the answer comes out shifted by one (2 3 4 5 1 for k = 5). Check for the zero case before cutting.

Shifting like an array, one step per k
✗ for (int i = 0; i < k; i++) { // walk to the last node, move it to the front }
✓ Count n once, close the circle, cut once.

Pattern confusion: an array can rotate by moving values in place, but a linked list rotates by moving one link. Repeating the array idea walks the whole list on every shift. On the dry run (1 → 2 → 3 → 4 → 5, k = 7), this loop does 7 shifts, and each one walks all 5 nodes: 35 steps. Only 7 % 5 = 2 shifts change the answer, and the one-pass plan takes 7 node visits (5 to count, 2 to reach the cut). With k near 2 × 10^9 the loop is far too slow.

Forgetting to cut the circle
✗ tail->next = head; ListNode* newTail = head; for (int i = 0; i < n - k % n - 1; i++) newTail = newTail->next; return newTail->next; // the list still loops back to the head
✓ ListNode* newHead = newTail->next; newTail->next = nullptr; // cut here return newHead;

Joining the tail to the head makes a circle. If you return without cutting the link after newTail, the list never ends, and any traversal loops forever. The cut is a required link change, not an optional step.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Linked List — Reversal translate into production architectures and low-level memory mechanics.