Rotate an array by k

Reverse the whole array, then reverse the first k, then reverse the rest. Three passes, every element moved exactly twice, O(1) extra space. The slice version a[-k:] + a[:-k] is one line and allocates a second array.

Overview

The problem

Rotate an array right by k positions, in place.

[1,2,3,4,5,6,7], k = 3 → [5,6,7,1,2,3,4]

The Python one-liner is nums[:] = nums[-k:] + nums[:-k], which allocates O(n) extra space. The interview version asks for O(1) extra space, and there is a neat answer.

First, normalise k: k %= len(nums). Rotating by the length is a no-op, and k can be larger than the array — forgetting this is the most common bug.

Lists & arraysCoding problemMedium

Step through it

What to watch

  • After the first reversal the blocks are in the right places, backwards.
  • Each subsequent reversal fixes one block.
  • Nothing is allocated — every step is in-place swapping.

Say this out loud

"Three reversals: whole thing, first k, then the rest. O(n) time, O(1) space. And k needs to be k % n first, or a k larger than the array breaks it."

Rotate an array by k

Rotate an array right by k positions, in place.

Run it

The three-reversal rotation printed after each step, checked against the slice version for every k from 0 to n, including the values larger than the array.

1Python
Output
2Python
Output
3Python
Output

The three-reversal trick

4Python
Output

O(n) time, O(1) space, and three simple loops.

Tracing [1,2,3,4,5,6,7] with k = 3:

StepArray
Start[1,2,3,4,5,6,7]
Reverse all[7,6,5,4,3,2,1]
Reverse first 3[5,6,7,4,3,2,1]
Reverse last 4[5,6,7,1,2,3,4]

Why it works: reversing the whole array puts the last k elements at the front, in reverse order, and the first n−k at the back, also reversed. Reversing each section separately un-reverses them. Every element ends where it should.

Why three reversals work

A right rotation by k moves the last k elements to the front and slides the rest along. Reversing the whole array puts those k at the front immediately — but reversed, and the other block reversed too. Reversing each block separately undoes exactly that.

Total work is 3·n/2 swaps, so O(n) time, and the only storage is a couple of indices.

The modulo, and the empty case

k %= n first. A k larger than the array is a rotation of k % n, and without the modulo the block boundaries go out of range. A k that is a multiple of n leaves the array unchanged, which the modulo also handles for free.

Negative k is a left rotation. Python's % already returns a non-negative result for a positive divisor, so k %= n converts it correctly — a detail worth mentioning because it differs from C.

The alternatives

Slice assignment — the Pythonic answer, O(n) space:

5Python
Output

The nums[:] = is important: assigning nums = ... rebinds the local name and leaves the caller's list unchanged. In-place modification requires slice assignment.

Cyclic replacement — O(1) space, moving each element directly to its final position:

6Python
Output

Correct, O(1) space, and considerably harder to get right — the outer loop exists because the permutation may consist of several disjoint cycles, and the number of cycles is gcd(n, k).

collections.deque.rotate(k) does it in one call if the container can be a deque, and it is O(k).

ApproachTimeSpaceClarity
Slice assignmentO(n)O(n)Best
Three reversalsO(n)O(1)Good
Cyclic replacementO(n)O(1)Poor
deque.rotateO(k)O(1)Best, if a deque is allowed

Edge cases

CaseHandling
k = 0No change — return early
k = nNo change, after k %= n
k > nk %= n reduces it
k negativeLeft rotation; convert with k %= n in Python, which handles it
Empty arrayk %= 0 raises — guard first
Single elementNo change

The empty-array case is worth handling explicitly, because % by zero raises ZeroDivisionError and the guard is one line.

Python's % on negatives is helpful here: -3 % 7 is 4, so a negative k automatically becomes the equivalent right rotation. In languages where % follows the sign of the dividend, that needs an explicit adjustment — a good detail to mention.

Rotating left, and by other units

Left rotation by k is right rotation by n - k. Either convert, or reorder the three reversals: reverse the first k, reverse the rest, reverse the whole thing.

Rotating a matrix by 90° is a related classic and uses a similar decomposition: transpose, then reverse each row. Same idea — a rotation expressed as two simpler in-place operations.

Rotating a linked list requires finding the new tail by walking n - k nodes, then relinking. O(n) time, O(1) space, and no reversal needed.

Rotating a string is the same three-reversal algorithm on a character list, which is how "abcdef" becomes "defabc".

A neat related check: is B a rotation of A? Test whether B in A + A, which works because every rotation of A appears as a substring of A doubled.

Where rotation appears in practice

  • Circular buffers. Ring buffers in audio, networking and logging are rotation by index arithmetic rather than by moving data — which is the better answer when it is available.
  • Round-robin scheduling and load balancing.
  • Caesar and rotation ciphers.
  • Image and matrix transforms.
  • Carousel and slideshow interfaces.
  • Rotated sorted array search, the common follow-up problem — binary search on an array that has been rotated by an unknown amount.

The circular-buffer point is the practically important one: if you find yourself rotating an array repeatedly, you probably want an offset variable instead. Keeping a logical start index and computing (i + offset) % n on access is O(1) per rotation and moves no data at all.

What it is testing

Do you normalise k? k %= n is the line most first attempts omit, and k > n is always in the test suite.

Do you get O(1) space? The slice version is correct and allocates; the three-reversal version is the expected improvement.

Do you know nums[:] = versus nums =? A real Python distinction, and rebinding silently fails to modify the caller's list.

Can you explain why three reversals work? Reciting the steps is weaker than explaining that reversing the whole array places the sections correctly but internally backwards.

Do you suggest an offset instead when told rotation happens often? That is the answer a systems-minded interviewer is hoping for.

Recap in one screen

  • Normalise with k %= n first; k can exceed the length, and that is always tested.
  • Reverse the whole array, then the first k, then the rest — O(n) time, O(1) space.
  • nums[:] = ... modifies in place; nums = ... only rebinds the local name.
  • Left rotation by k is right rotation by n−k.
  • If rotation is frequent, keep an offset and index modulo n rather than moving data.

How the code works

The three-reversal rotation printed after each step, checked against the slice version for every k from 0 to n, including the values larger than the array.

How the code works

  1. k %= nThe first line, and the one that is usually missing. A k larger than the array sends reverse an out-of-range bound — it raises rather than returning something wrong, which the last block demonstrates.
  2. reverse(a, 0, n - 1)Puts the last k elements at the front in one pass — backwards, along with everything else, which the next two reversals correct.
  3. reverse(a, 0, k - 1) then reverse(a, k, n - 1)Each fixes one block. The boundary is exactly k, which is why the modulo has to happen before any of this.
  4. a[-k:] + a[:-k]The version to offer first. It is correct and readable, and it allocates a whole second array — which is the requirement the question is really about.

Change one thing

  • Pass a negative k. Python's % turns it into the equivalent left rotation for free, unlike C.
  • Implement the cyclic-replacement version. Every element moves once instead of twice, and you need gcd(n, k) starting points.

Where this runs

Real CPython, compiled to WebAssembly and running on your own machine — nothing is uploaded. The first run takes a few seconds while the interpreter downloads; after that it is immediate. Need more room, or want to paste your own attempt? Use the Python compiler.

Check yourself

0 of 3

Answer without scrolling back up.

  1. The three-reversal rotation uses how much extra space?

  2. Why is `k %= n` needed before the reversals?

  3. After reversing the whole array, why reverse each block again?

Cheat sheet

Rotate an array by k

Reverse the whole array, then reverse the first k, then reverse the rest. Three passes, every element moved exactly twice, O(1) extra space. The slice version a[-k:] + a[:-k] is one line and allocates a second array.

INTERVIEW · vizlearn.in/interview/rotate-an-array.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.