medium

Rotate List

Rotate a list right by k places by measuring it, closing it into a ring, and cutting it open again.

1. Define the problem

Rotate List

Rotate a linked list to the right by k places, which means the last k nodes move to the front and everything else slides along behind them. The function takes a plain array of values and the number k, builds the list inside, and returns a plain array. Instead of moving nodes one at a time, join the tail back to the head to make a ring , then cut the ring open at the right place. Because rotating by the full length changes nothing, k is first reduced with a remainder.

Constraints

  • The number of nodes is between 0 and 500
  • -100 ≤ node value ≤ 100
  • 0 ≤ k ≤ 2 × 109
  • k can be far larger than the number of nodes

Example

Inputvalues = [1, 2, 3, 4, 5], k = 2
Output[4, 5, 1, 2, 3]

Explanation The last two nodes, 4 and 5, move to the front, and 1, 2, 3 follow them.

2. Know the words first

In plain terms

Rotate right
Shift every node k places towards the back; nodes that fall off the end reappear at the front. Rotating [1, 2, 3] by 1 gives [3, 1, 2].
Tail
The last node of the list — the one whose next pointer aims at nothing.
Remainder (k % length)
What is left of k after removing whole loops around the list. Rotating a 5-node list by 7 lands in the same place as rotating it by 2.
Ring
A list whose tail points back at the head, so there is no end. It is a temporary shape here: the ring is cut open again before returning.
3. Visualize the solution

Each cell is one node in its original position, head first

Each cell is one node in its original position, head first
Statusinit

The list is 1 -> 2 -> 3 -> 4 -> 5 and it must rotate right by 2.

What happens in this step

list = 1 -> 2 -> 3 -> 4 -> 5
k = 2

The last two nodes should end up at the front, giving 4 -> 5 -> 1 -> 2 -> 3.
Step 1 of 6

Steps to visualize

  1. The cells stay where they are; what changes is where the list starts and ends.
  2. First walk to the tail to learn the length of the list.
  3. Reduce k with a remainder, because whole loops around the list change nothing.
  4. Count to the new tail: the node that will become the last one.
  5. Cut there, then join the old tail to the old head, and the node after the cut becomes the new head.
4. Walk through the code

Walk through the code

Same walkthrough, now with the code. Press Next to move one step and watch which lines run.

Each cell is one node in its original position, head first
Statusinit

The list is 1 -> 2 -> 3 -> 4 -> 5 and it must rotate right by 2.

What happens in this step

list = 1 -> 2 -> 3 -> 4 -> 5
k = 2

The last two nodes should end up at the front, giving 4 -> 5 -> 1 -> 2 -> 3.
Step 1 of 6
5. Solution

Solution

solution.tsTypeScript
class ListNode {
  constructor(val, next = null) {
    this.val = val;
    this.next = next;
  }
}

function toList(values) {
  let head = null;
  for (let i = values.length - 1; i >= 0; i--) {
    head = new ListNode(values[i], head);
  }
  return head;
}

function toArray(head) {
  const out = [];
  for (let node = head; node !== null; node = node.next) {
    out.push(node.val);
  }
  return out;
}

function rotateRight(values, k) {
  const head = toList(values);
  if (head === null || head.next === null || k === 0) {
    return toArray(head);
  }

  let length = 1;
  let tail = head;
  while (tail.next !== null) {
    tail = tail.next;
    length++;
  }

  const shift = k % length;
  if (shift === 0) {
    return toArray(head);
  }

  let newTail = head;
  for (let i = 1; i < length - shift; i++) {
    newTail = newTail.next;
  }

  const newHead = newTail.next;
  newTail.next = null;
  tail.next = head;

  return toArray(newHead);
}
Time
O(n)
Space
O(n)
6. Test cases

Test cases

InputExpectedCovers
values = [1, 2, 3, 4, 5], k = 2[4, 5, 1, 2, 3]example from the description
values = [0, 1, 2], k = 4[2, 0, 1]k is larger than the list, so the remainder matters
values = [], k = 3[]empty list, nothing to rotate
values = [7], k = 99[7]one node always rotates onto itself
values = [1, 2, 3], k = 3[1, 2, 3]rotating by exactly the length changes nothing
values = [-1, 0, 4, 8, 2, 5, 7], k = 10[2, 5, 7, -1, 0, 4, 8]a longer list with negative values and k above the length