Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
Rotate the array right by k steps in-place. First reduce k with k %= n (k can exceed n). The O(1)-space trick is three reversals: reverse the whole array, then reverse the first k elements, then reverse the remaining n−k. That lands every element in its rotated position without an auxiliary array. O(n) time, O(1) space.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you remember k %= n, and whether you know the three-reversal O(1)-space rotation rather than only the easy extra-array copy.
Where candidates slip
Forgetting k %= n (TLE or out-of-bounds when k > n), or rotating one element at a time k times, which is O(n·k).
How to stand out
Start with the O(n)-space index map to prove correctness, then deliver the three-reversal O(1) method and explain WHY the reversals compose into a rotation.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Interactive decision treeInteractiveChoose the right approachFirst decision previewRotate array right by k stepsExtra O(n) space allowed?YesNoExplore the full treeCollapse the tree
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 2
Extra Array via Index Mapping (Brute / Correctness Proof)
1Hint 1Explore hintHide hint
Where does the element at index i end up after a right rotation by k? Write the destination index as a formula.
2Hint 2Explore hintHide hint
Element i moves to (i + k) % n. Allocate a fresh array and place each element directly at its destination.
3Hint 3Explore hintHide hint
Copy the result back into nums so the rotation is 'in-place' from the caller's view, even though we used a temp array.
A · Core idea
The most reliable way to understand the rotation is to write the destination of each element as a closed-form index, then just place elements there.
The mapping is the entire problem. A right rotation by k sends the element at index i to index (i + k) mod n. The mod n is what implements the wrap-around: when i + k runs off the end, it cycles back to the front. Element n−1 with k = 3, n = 7 goes to (6 + 3) % 7 = 2, which is exactly where the old last element should land after three elements wrap around. Filling a fresh array by this rule can't go wrong — there's no shifting, no overwriting order to worry about, every element is dropped directly into its final home.
Why `k %= n` matters even here. If k ≥ n, (i + k) % n still works mathematically, but reducing k first keeps the intent obvious and avoids surprises in languages where % on large values is awkward. It also makes the connection to the three-reversal method (which requires k < n for the split point) explicit.
Why this isn't the final answer. The interviewer's follow-up is almost always 'can you do it with O(1) extra space?'. The temp array is O(n) memory we'd love to avoid. But this version earns its keep: it gives you an unambiguous correctness reference to check the trickier in-place method against. State it, then say 'we can avoid the extra array with reversals.'
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
nums = [1,2,3,4,5,6,7], k = 3i=0
out[3] = 1
out = [_,_,_,1,_,_,_][5,6,7,1,2,3,4]C · Code with teaching comments
Reference implementation previewpublic void rotate(int[] nums, int k) { int n = nums.length; k %= n; int[] out = new int[n]; for (int i = 0; i < n; i++) {Explore the full codeHide the full code
D · Why it works and complexityO(n) timeO(n) spaceOpen the invariant and proofExplore the proofHide the proof
Naming the destination formula (i + k) % n converts a vague 'shift things over' into a precise placement rule. Every correct rotation method must reproduce this mapping — it's your ground truth.
ComplexityO(n) time, O(n) space — One pass to fill the temp array plus one pass to copy back → O(n) time. The temp array of size n → O(n) extra space.
E · Edge cases and pitfalls5nums = [1], k = 100 — k %= 1 = 0 → out[i] = nums[i] → unchanged.Explore edge casesHide edge cases
Edge cases handled
nums = [1], k = 100k %= 1 = 0 → out[i] = nums[i] → unchanged.k = 0Every element maps to its own index → array unchanged.
Pitfalls
- Using `return nums[:]` in Python or reassigning nums = out — that rebinds the local name and doesn't mutate the caller's list; use nums[:] = out.
- Skipping k %= n and indexing out of range when k > n.
- Claiming this is O(1) space — it isn't; be honest about the temp array.
Approach 2 of 2 · Optimal
Three Reversals (Optimal, O(1) Space)
1Hint 1Explore hintHide hint
After k %= n, the answer is the last k elements followed by the first n−k elements. What does reversing the entire array do to those two blocks?
2Hint 2Explore hintHide hint
Reverse the whole array: now the last k elements are at the front but in reversed order, and the first n−k are at the back, also reversed.
3Hint 3Explore hintHide hint
Reverse the first k elements to fix their order, then reverse the remaining n−k to fix theirs. Three in-place reversals, each a two-pointer swap.
A · Core idea
The target layout after a right rotation by k is: last `k` elements, then first `n−k` elements, each block keeping its internal order. The three-reversal trick reaches that layout using only swaps.
Step 1 — reverse the whole array. Take [1,2,3,4,5,6,7] with k = 3. Reversing everything gives [7,6,5,4,3,2,1]. Look at what happened structurally: the last k = 3 elements (5,6,7) are now at the front — exactly where they belong — but in reversed order (7,6,5). Likewise the first n−k = 4 elements (1,2,3,4) are now at the back, reversed to (4,3,2,1). So one global reverse puts both blocks in the right region but with their internal order flipped.
Step 2 — reverse the first `k`. Reversing nums[0..k) un-flips the front block: [7,6,5] → [5,6,7]. The array is now [5,6,7,4,3,2,1]. The front is finished.
Step 3 — reverse the last `n−k`. Reversing nums[k..n) un-flips the back block: [4,3,2,1] → [1,2,3,4], giving [5,6,7,1,2,3,4] — the rotation, done.
Why this composes correctly in general. Reversal is an involution that maps position j within a segment to its mirror. Doing it globally then locally is algebraically equivalent to a cyclic shift: the global reverse sends index i to n−1−i; reversing the two sub-segments then sends each element to precisely (i + k) mod n — the same destination the index-map method computed. That equivalence is why you can trust it matches the brute-force ground truth.
Why `k %= n` is mandatory here. The split point for steps 2 and 3 is index k. If k ≥ n, that split is out of bounds and the reversals are nonsensical. Reducing k modulo n first guarantees 0 ≤ k < n so the two sub-segments are well-defined (and k = 0 becomes three no-op reverses, correctly leaving the array unchanged).
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
nums = [1,2,3,4,5,6,7], k = 3Array state
start
original
[5,6,7,1,2,3,4]C · Code with teaching comments
D · Why it works and complexityO(n) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
Reverse-all-then-reverse-blocks is the canonical O(1)-space way to translate or rotate a sequence. The global reverse parks each block in the correct half; two local reverses repair the internal order. The same three-step move rotates strings and reorders words in a sentence.
ComplexityO(n) time, O(1) space — Each element is touched by exactly one reversal (the whole-array reverse counts as one), so total swaps ≈ n → O(n) time. Reversal swaps in place with two indices → O(1) space.
E · Edge cases and pitfalls6nums = [1,2], k = 3 — k %= 2 = 1 → reverse(0,1)→[2,1], reverse(0,0) no-op, reverse(1,1) no-op → [2,1].Explore edge casesHide edge cases
Edge cases handled
nums = [1,2], k = 3k %= 2 = 1 → reverse(0,1)→[2,1], reverse(0,0) no-op, reverse(1,1) no-op → [2,1].k % n == 0k becomes 0 → reverse(0,n-1) then reverse(0,-1) and reverse(0,n-1): the two full reverses cancel, leaving the array unchanged.nums = [9], k = 5k %= 1 = 0 → all reverses are no-ops → [9].
Pitfalls
- Forgetting k %= n — reverse(0, k-1) with k > n is out of bounds.
- Reversing the blocks before the whole array — rotates left instead of right.
- Off-by-one in the reverse bounds: it's reverse(0, k-1) and reverse(k, n-1), inclusive endpoints.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic void rotate(int[] nums, int k) { int n = nums.length; k %= n; reverse(nums, 0, n - 1); reverse(nums, 0, k - 1);Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
1Skipping k %= n
k can be up to 10⁵ regardless of n. Without reduction, reverse(0, k-1) indexes past the array (Java throws) and a step-by-step rotation does k full passes (TLE).
Explore the code comparisonHide the code comparison
Skipping k %= n
k can be up to 10⁵ regardless of n. Without reduction, reverse(0, k-1) indexes past the array (Java throws) and a step-by-step rotation does k full passes (TLE).
Don't write this
public void rotate(int[] nums, int k) {
int n = nums.length;
reverse(nums, 0, n - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, n - 1);
}Write this instead
public void rotate(int[] nums, int k) {
int n = nums.length;
k %= n;
reverse(nums, 0, n - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, n - 1);
}2Rebinding instead of mutating in Python
rotate must mutate nums in place. Assigning nums = out (or returning a new list) only changes the local reference; the caller's array is untouched.
Explore the code comparisonHide the code comparison
Rebinding instead of mutating in Python
rotate must mutate nums in place. Assigning nums = out (or returning a new list) only changes the local reference; the caller's array is untouched.
Don't write this
def rotate(self, nums, k):
k %= len(nums)
nums = nums[-k:] + nums[:-k]Write this instead
def rotate(self, nums, k):
k %= len(nums)
nums[:] = nums[-k:] + nums[:-k]3One-step-at-a-time rotation
Popping the last element and inserting it at the front k times is O(n) per step → O(n·k). With n,k up to 1e5 that's 1e10 operations — TLE.
Explore the code comparisonHide the code comparison
One-step-at-a-time rotation
Popping the last element and inserting it at the front k times is O(n) per step → O(n·k). With n,k up to 1e5 that's 1e10 operations — TLE.
Don't write this
for _ in range(k):
nums.insert(0, nums.pop())Write this instead
k %= len(nums)
nums[:] = nums[-k:] + nums[:-k] # or the three-reversal methodRevise
Carry the pattern into the interview
Pattern to remember
Reverse-whole then reverse-two-parts (in-place rotation)
Code pattern to memorize
k %= n
reverse(nums, 0, n - 1)
reverse(nums, 0, k - 1)
reverse(nums, k, n - 1)Rules to remember
- 1Always `k %= n` first — k can be larger than n, and rotating by n is a no-op.
- 2Right-rotate by k means the last k elements move to the front, in their original order.
- 3Three reversals: whole → first k → last n−k. Doing first-k before the whole reversal rotates the wrong way.
- 4The reversal swaps are a two-pointer walk from both ends toward the middle — O(1) space.
- 5The extra-array method is O(n) space but the clearest correctness proof:
out[(i + k) % n] = nums[i].
Use this pattern when
- Cyclically shift an array/string in-place with O(1) extra space
- Any 'rotate by k' where k may exceed the length
- Block-swap or array-realignment problems
- When the interviewer bans an auxiliary array
Choose another pattern when
- You may use O(n) extra space and want the simplest code → index-mapping copy
- Rotation is conceptual only (just need element at rotated index) → compute (i - k) % n on read, don't move data
- Linked list rotation → relink pointers, not reversals (LC 61)
- 2D matrix rotation → transpose + reflect, a different mechanic (LC 48)
Interview takeaway
Three reversals turn an O(n)-space rotation into O(1) space. The identity 'reverse all, then reverse each block' is the reusable insight — it also rotates strings and underlies the classic 'rotate words in a sentence' problem.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternReverse-all-then-reverse-blocks is the canonical O(1)-space rotation/translation of a sequence. Recognise it whenever you must cyclically shift an array or string in place. The destination identity (i + k) % n is the correctness anchor.
Practice queueDirect variations and pattern siblings
Direct follow-ups
- Rotate ListComing soonLinked list: form a cycle, find the new tail at length - k%length, then break the cycle.
- Rotate ImageComing soon2D 90° rotation = transpose then reverse each row, all in place.
- Reverse Words in a String IIComing soonSame reverse-all-then-reverse-blocks idea applied to words in a char array.
- Rotate FunctionComing soonDerive F(k) from F(k-1) with a recurrence instead of materializing each rotation.