Definition
- Array rotation – moves each element K places to the right, with elements falling off the end wrapping to the front.
- Triple reversal – reverse the entire array, then reverse the first K elements, then reverse the remaining n - K elements.
- Modulo reduction –
K = K % nhandles rotations larger than the array length. - O(n) time, O(1) space – three in-place reversals with no auxiliary array.
- Alternatives – copying to a new array uses O(n) space; rotating one step at a time is O(n * K).
The National Bank of India keeps a rolling window of Rajesh's recent daily balances, and at day-end it must shift the window so the newest days appear first. Imagine the days written on a strip of paper. The clerk flips the whole strip over, then flips just the first part back, then flips the rest. After three flips the strip shows the days rotated into the new arrangement, all done on one strip without copying to a new one.
Understanding the Concepts
What is array rotation?
Rotating an array to the right by K positions moves each element K places to the right, with elements that fall off the end wrapping around to the front. For example, rotating [1, 2, 3, 4, 5] right by 2 gives [4, 5, 1, 2, 3].
Why reduce K modulo n first?
If the array has length n and K >= n, rotating by K is the same as rotating by K % n, because every full n rotations return to the start. Skipping this step sends indices out of range.
k = k % n;
if (k < 0) k += n; // convert negative K to equivalent right rotation
How does the triple reversal work?
Reversing the whole array puts the last K elements at the front but in reverse order, and the first n - K elements at the back also in reverse. Reversing the first K elements fixes the front block, and reversing the remaining n - K elements fixes the back block.
Original: [1, 2, 3, 4, 5] K = 2 Step 1: Reverse whole → [5, 4, 3, 2, 1] Step 2: Reverse first K=2 → [4, 5, 3, 2, 1] Step 3: Reverse rest → [4, 5, 1, 2, 3] ← correct!
How do you implement it? (with code)
package com.bank.analysis;
import java.math.BigDecimal;
import java.util.Arrays;
public class RotateArray {
public static void rotate(BigDecimal[] balances, int k) {
int n = balances.length;
if (n <= 1) return;
k = k % n;
if (k < 0) k += n;
if (k == 0) return;
reverse(balances, 0, n - 1);
reverse(balances, 0, k - 1);
reverse(balances, k, n - 1);
}
private static void reverse(BigDecimal[] a, int left, int right) {
while (left < right) {
BigDecimal temp = a[left];
a[left] = a[right];
a[right] = temp;
left++;
right--;
}
}
public static void main(String[] args) {
BigDecimal[] balances = {
new BigDecimal("1000"), new BigDecimal("1500"),
new BigDecimal("1200"), new BigDecimal("1800"),
new BigDecimal("2000")
};
System.out.println("Before: " + Arrays.toString(balances));
rotate(balances, 2);
System.out.println("After: " + Arrays.toString(balances));
}
}
Before: [1000, 1500, 1200, 1800, 2000]
After: [1800, 2000, 1000, 1500, 1200]
How is triple reversal different from other approaches?
| Approach | Time | Space | Notes |
|---|---|---|---|
| Copy to new array | O(n) | O(n) | Simple but uses extra memory |
| Rotate one step K times | O(n * K) | O(1) | Too slow for large K |
| Triple reversal | O(n) | O(1) | Optimal in-place |
| Cyclic replacement (juggling) | O(n) | O(1) | Same bounds, harder to implement |
Why does the triple reversal produce the correct rotation?
Consider the array as two blocks: A = first n-K elements, B = last K elements. The original is [A | B]. We want [B | A].
- Reverse whole:
[A | B]becomes[B_rev | A_rev]. - Reverse first K: fixes B_rev to B.
- Reverse rest: fixes A_rev to A.
- Result:
[B | A].
What are the edge cases?
- K = 0 – no rotation needed.
- K = n – equivalent to K = 0 after modulo.
- K > n – modulo handles it.
- K < 0 (left rotation) – convert to right:
k = (k % n + n) % n. - Empty array – return immediately.
- Single element – return immediately.
What about left rotation vs right rotation?
Right rotation by K is equivalent to left rotation by n - K. Mixing up the direction is a common bug. Always state explicitly which direction and test with a small example.
// Right rotation by K:
reverse(a, 0, n-1); reverse(a, 0, k-1); reverse(a, k, n-1);
// Left rotation by K:
reverse(a, 0, k-1); reverse(a, k, n-1); reverse(a, 0, n-1);
What are common interview follow-up questions?
- Can you do it in O(1) space? – Yes, triple reversal or cyclic replacement.
- What about left rotation? – Reverse the first K, reverse the rest, reverse the whole.
- What if K is negative? – Convert to equivalent right rotation.
- Can you do it with a temporary variable for one element? – Yes, cyclic replacement uses O(1) extra.
Visual Overview
┌──────────────────────────────────────────────────────┐ │ Triple Reversal: Rotate Right by K │ ├──────────────────────────────────────────────────────┤ │ │ │ Original: [ A A A | B B ] K = 2 │ │ block A block B │ │ │ │ Step 1: Reverse whole │ │ [ B' B' | A' A' A' ] │ │ │ │ Step 2: Reverse first K=2 │ │ [ B B | A' A' A' ] ← B fixed │ │ │ │ Step 3: Reverse rest (n-K=3) │ │ [ B B | A A A ] ← A fixed │ │ │ │ Result: [ B B A A A ] = rotated right by 2 │ └──────────────────────────────────────────────────────┘
Key Takeaway
Rotating an array right by K moves each element K places to the right with wrap-around. The elegant in-place approach is the triple reversal: reverse the whole array, then reverse the first K elements, then reverse the rest. It runs in O(n) time with O(1) space.
Always reduce K modulo the length first, because rotating by more than the length is the same as rotating by K mod n. Also normalize a negative K into the equivalent right rotation and treat empty or single-element arrays as no-ops.
The triple reversal works because the original array is two blocks [A | B] and you want [B | A]. Reversing the whole array gives [B_rev | A_rev], reversing the first K fixes B, and reversing the rest fixes A. Compared with the alternatives, copying to a new array uses O(n) extra space and rotating one step at a time is O(n * K), so the triple reversal is the best in-place choice.
In a banking project at the National Bank of India, this rotates Rajesh's rolling window of daily closing balances at day-end so the trend chart aligns with a new reference day, doing it in place to avoid allocating a fresh array per customer per day.
Remember one sentence: Reduce K modulo n, then reverse the whole array, reverse the first K, and reverse the rest to rotate in O(n) time and O(1) space.
---