Lesson 11 of 164
Rotate Array
Given an array nums and a non-negative integer k, rotate the array to the right by k positions: every element moves k places right, and elements that fall off the end wrap around to the front. Do it in place.
LeetCode: 189. Rotate Array
Example 1
Input: nums = [1, 2, 3, 4, 5, 6, 7], k = 3
Output: [5, 6, 7, 1, 2, 3, 4]
Explanation:
rotate 1: [7, 1, 2, 3, 4, 5, 6]
rotate 2: [6, 7, 1, 2, 3, 4, 5]
rotate 3: [5, 6, 7, 1, 2, 3, 4]Example 2
Input: nums = [-1, -100, 3, 99], k = 6
Output: [3, 99, -1, -100]
Explanation: rotating 4 positions gives back the original array, so k = 6 is the same as k = 2.In every approach, reduce k first with k % n, since rotating by n changes nothing.
Brute force: rotate by one, k times
A rotation by one saves the last element, shifts everything else one place right, and puts the saved element at index 0. Repeat k times.
import java.util.Arrays;
public class Main {
static void rotate(int[] nums, int k) {
int n = nums.length;
if (n == 0) {
return;
}
for (int step = 0; step < k % n; step++) {
int last = nums[n - 1];
for (int i = n - 1; i >= 1; i--) {
nums[i] = nums[i - 1];
}
nums[0] = last;
}
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6, 7};
int[] b = {-1, -100, 3, 99};
rotate(a, 3);
rotate(b, 6);
System.out.println(Arrays.toString(a) + " " + Arrays.toString(b));
}
}[5, 6, 7, 1, 2, 3, 4] [3, 99, -1, -100]Time: O(n·k). Space: O(1).
Better: copy into a new array
Element i belongs at position (i + k) % n. Write each element to its new position in a copy, then copy back.
import java.util.Arrays;
public class Main {
static void rotate(int[] nums, int k) {
int n = nums.length;
if (n == 0) {
return;
}
int[] rotated = new int[n];
for (int i = 0; i < n; i++) {
rotated[(i + k) % n] = nums[i];
}
System.arraycopy(rotated, 0, nums, 0, n);
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6, 7};
rotate(a, 3);
System.out.println(Arrays.toString(a));
}
}[5, 6, 7, 1, 2, 3, 4]Time: O(n). Space: O(n) for the copy. i + k is an int sum, so it can overflow when k is close to Integer.MAX_VALUE. Reduce k with k % n first.
Optimal: three reversals
Rotating right by k moves the last k elements to the front, keeping the order inside each part. Reversing the whole array puts those k elements first, but each part is now backwards. Reversing each part again fixes that.
Walkthrough with [1, 2, 3, 4, 5, 6, 7], k = 3:
| step | array |
|---|---|
| start | [1, 2, 3, 4, 5, 6, 7] |
| reverse all | [7, 6, 5, 4, 3, 2, 1] |
| reverse first k = 3 | [5, 6, 7, 4, 3, 2, 1] |
| reverse the remaining 4 | [5, 6, 7, 1, 2, 3, 4] |
Java has no built-in reverse for a range of an int[], so a helper reverse(nums, from, to) swaps elements from both ends of the inclusive range [from, to].
import java.util.Arrays;
public class Main {
static void reverse(int[] nums, int from, int to) { // inclusive range
while (from < to) {
int tmp = nums[from];
nums[from] = nums[to];
nums[to] = tmp;
from++;
to--;
}
}
static void rotate(int[] nums, int k) {
int n = nums.length;
if (n == 0) {
return;
}
k = k % n;
reverse(nums, 0, n - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, n - 1);
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6, 7};
int[] b = {-1, -100, 3, 99};
rotate(a, 3);
rotate(b, 6);
System.out.println(Arrays.toString(a) + " " + Arrays.toString(b));
}
}[5, 6, 7, 1, 2, 3, 4] [3, 99, -1, -100]Time: O(n): each element is swapped at most twice. Space: O(1).
When k is 0, reverse(nums, 0, -1) does nothing, because from < to is false.
In real code
Collections.rotate(list, distance) rotates a List to the right by distance positions in place. It reduces the distance modulo the list size itself, so any non-negative or negative distance is safe, and an empty list does nothing.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7));
Collections.rotate(nums, 3);
System.out.println(nums);
Collections.rotate(nums, -3); // a negative distance rotates left
System.out.println(nums);
}
}[5, 6, 7, 1, 2, 3, 4]
[1, 2, 3, 4, 5, 6, 7]Edge cases
- Empty array: nothing to do (and
k % 0would throwArithmeticException, hence the early return). kis a multiple ofn: the array is unchanged.klarger thann: reduced byk % n.- Rotate left by
k: the same as rotating right byn - k % n.
