Rotate Array — The Triple-Reverse Trick
Rotate an array by k steps in O(1) extra space using the triple-reverse trick. Compare it with the extra-array approach and learn why this pattern keeps showing up.
What you'll learn
- ✓The simple extra-array solution and its cost
- ✓Why the triple-reverse trick rotates in place
- ✓Handling k larger than the array length
- ✓A cyclic-replacement alternative and why it is tricky
- ✓When in-place rotation matters in real systems
Prerequisites
- •Basics of arrays and indexing
Rotate Array sounds trivial: shift every element of an array k positions to the right. But the in-place version trips up a lot of candidates because the obvious approach uses extra memory, and the elegant one is one of those tricks that only feels obvious after you have seen it.
The Problem
Given an integer array nums and an integer k, rotate the array to the right by k steps. k can be larger than the array length.
Example: nums = [1,2,3,4,5,6,7], k = 3 becomes [5,6,7,1,2,3,4].
Intuition
The straightforward solution is to allocate a new array and copy each element nums[i] to position (i + k) % n in the new array. That is O(n) time and O(n) space.
For the O(1) extra-space version, the trick is the triple reverse. Reversing a subarray in place uses no extra memory. Three well-chosen reversals produce the rotation:
- Reverse the entire array.
- Reverse the first
kelements. - Reverse the remaining
n - kelements.
Why it works: think of the array as two blocks [A][B] where |B| = k. You want [B][A]. Reversing the whole array yields [reverse(B), reverse(A)]. Then reversing each block restores their internal order, leaving [B][A]. The two blocks have been swapped without allocating anything.
Don’t forget k %= n first. If k exceeds n you would otherwise loop multiple times needlessly.
Explanation with Example
Walk through [1,2,3,4,5,6,7], k = 3:
- 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].
Done.
start [ 1 2 3 4 5 6 7 ]
| k=3 |
reverse all [ 7 6 5 4 3 2 1 ]
| k=3 |
reverse 0..k-1[ 5 6 7 | 4 3 2 1 ]
reverse k..n-1[ 5 6 7 | 1 2 3 4 ]
^^^^^^^^^ ^^^^^^^^^^^^
last k first n-k
(rotated) before: [ A | B ] |B| = k
rev all: [ rev(B) | rev(A) ]
rev L,R: [ B | A ] blocks swapped Code
def rotate(nums, k):
n = len(nums)
k %= n
def reverse(l, r):
while l < r:
nums[l], nums[r] = nums[r], nums[l]
l += 1
r -= 1
reverse(0, n - 1)
reverse(0, k - 1)
reverse(k, n - 1)class Solution {
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);
}
private void reverse(int[] a, int l, int r) {
while (l < r) {
int t = a[l]; a[l] = a[r]; a[r] = t;
l++; r--;
}
}
}class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
k %= n;
reverse(nums.begin(), nums.end());
reverse(nums.begin(), nums.begin() + k);
reverse(nums.begin() + k, nums.end());
}
};Edge Cases
k == 0: no work. The modulo handles it naturally.k == n: also no work afterk %= n.n == 1: any rotation is a no-op.knegative: not in the standard problem, but if it appears, normalize withk = ((k % n) + n) % n.- Empty array: handle
n == 0first to avoid division by zero ink % n.
Complexity Analysis
- Triple reverse: O(n) time, O(1) extra space. Each element is touched at most twice across the three reversals.
- Extra array: O(n) time, O(n) space.
How to Explain It in an Interview
Mention both the extra-array approach (which works, but uses O(n) memory) and the triple reverse (which works in place). Sketch why the triple reverse works using the block-swap argument. Always state k %= n explicitly, because forgetting it is the bug interviewers expect.
If asked for yet another approach, mention cyclic replacements: start at index 0, place its value at the rotated position, displace the value that was there, and continue until you have moved n elements. The catch is that if gcd(n, k) > 1 you end up in a shorter cycle and need to restart from the next index. The triple-reverse is shorter, easier to prove, and harder to get wrong.
Related Problems
- Rotate Image (transpose plus row reverse)
- Reverse Words in a String
- Reverse Linked List
Wrap up
In-place rotation shows up in ring buffers, circular queues, streaming windows, and image processing kernels. Once you have the triple-reverse trick in your toolkit, you start seeing it everywhere. A clean primitive like “reverse a subarray” combines into surprisingly powerful transformations.
Related articles
- DSA Find Minimum in Rotated Sorted Array — Binary Search
Solve Find Minimum in Rotated Sorted Array in logarithmic time with a modified binary search. Learn the pivot-finding invariant, edge cases, and how to extend the pattern to related problems.
- DSA Maximum Product Subarray — Tracking Min and Max
Solve Maximum Product Subarray in linear time by tracking running min and max. Learn why negative numbers flip the role of min and max and see clean code.
- DSA Reverse String — Two-Pointer In-Place Solution
Solve the Reverse String problem in place using the two-pointer technique. Walkthrough, complexity analysis, edge cases, and clean Java, Python, and C++ implementations.
- DSA Best Time to Buy and Sell Stock — One-Pass Min Tracker
Walk through Best Time to Buy and Sell Stock. We go from the quadratic brute force to a clean one-pass solution tracking the running minimum.