BAEL-6913 - Rotate array in java (#14861)
* feat: rotate array in java * fix: When to when
This commit is contained in:
parent
daaefb0f26
commit
d5b2f61ea0
@ -0,0 +1,102 @@
|
|||||||
|
package com.baeldung.algorithms.rotatearray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To speed up the rotation, we narrow k rotations to the remainder of k divided by the array length, or k module the array length.
|
||||||
|
* Therefore, a large rotation number will be translated into the relative smallest rotation.
|
||||||
|
* All solutions replace the original array, although they might use an extra array to compute the rotation.
|
||||||
|
*/
|
||||||
|
public class RotateArray {
|
||||||
|
|
||||||
|
private RotateArray() {
|
||||||
|
throw new IllegalStateException("Rotate array algorithm utility methods class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param arr array to apply rotation to
|
||||||
|
* @param k number of rotations
|
||||||
|
*/
|
||||||
|
public static void bruteForce(int[] arr, int k) {
|
||||||
|
checkInvalidInput(arr, k);
|
||||||
|
|
||||||
|
k %= arr.length;
|
||||||
|
int temp;
|
||||||
|
int previous;
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
previous = arr[arr.length - 1];
|
||||||
|
for (int j = 0; j < arr.length; j++) {
|
||||||
|
temp = arr[j];
|
||||||
|
arr[j] = previous;
|
||||||
|
previous = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param arr array to apply rotation to
|
||||||
|
* @param k number of rotations
|
||||||
|
*/
|
||||||
|
public static void withExtraArray(int[] arr, int k) {
|
||||||
|
checkInvalidInput(arr, k);
|
||||||
|
|
||||||
|
int[] extraArray = new int[arr.length];
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
extraArray[(i + k) % arr.length] = arr[i];
|
||||||
|
}
|
||||||
|
System.arraycopy(extraArray, 0, arr, 0, arr.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param arr array to apply rotation to
|
||||||
|
* @param k number of rotations
|
||||||
|
*/
|
||||||
|
public static void cyclicReplacement(int[] arr, int k) {
|
||||||
|
checkInvalidInput(arr, k);
|
||||||
|
|
||||||
|
k = k % arr.length;
|
||||||
|
int count = 0;
|
||||||
|
for (int start = 0; count < arr.length; start++) {
|
||||||
|
int current = start;
|
||||||
|
int prev = arr[start];
|
||||||
|
do {
|
||||||
|
int next = (current + k) % arr.length;
|
||||||
|
int temp = arr[next];
|
||||||
|
arr[next] = prev;
|
||||||
|
prev = temp;
|
||||||
|
current = next;
|
||||||
|
count++;
|
||||||
|
} while (start != current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param arr array to apply rotation to
|
||||||
|
* @param k number of rotations
|
||||||
|
*/
|
||||||
|
public static void reverse(int[] arr, int k) {
|
||||||
|
checkInvalidInput(arr, k);
|
||||||
|
|
||||||
|
k %= arr.length;
|
||||||
|
reverse(arr, 0, arr.length - 1);
|
||||||
|
reverse(arr, 0, k - 1);
|
||||||
|
reverse(arr, k, arr.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void reverse(int[] nums, int start, int end) {
|
||||||
|
while (start < end) {
|
||||||
|
int temp = nums[start];
|
||||||
|
nums[start] = nums[end];
|
||||||
|
nums[end] = temp;
|
||||||
|
start++;
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkInvalidInput(int[] arr, int rotation) {
|
||||||
|
if (rotation < 1 || arr == null)
|
||||||
|
throw new IllegalArgumentException("Rotation must be greater than zero or array must be not null");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
package com.baeldung.algorithms.rotatearray;
|
||||||
|
|
||||||
|
import static com.baeldung.algorithms.rotatearray.RotateArray.bruteForce;
|
||||||
|
import static com.baeldung.algorithms.rotatearray.RotateArray.cyclicReplacement;
|
||||||
|
import static com.baeldung.algorithms.rotatearray.RotateArray.reverse;
|
||||||
|
import static com.baeldung.algorithms.rotatearray.RotateArray.withExtraArray;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class RotateArrayUnitTest {
|
||||||
|
|
||||||
|
private final int[] arr = { 1, 2, 3, 4, 5, 6 };
|
||||||
|
private final int rotationLtArrayLength = 1;
|
||||||
|
private final int rotationGtArrayLength = arr.length + 2;
|
||||||
|
private final int[] ltArrayLengthRotation = { 6, 1, 2, 3, 4, 5 };
|
||||||
|
private final int[] gtArrayLengthRotation = { 5, 6, 1, 2, 3, 4 };
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenNoRotationOrEmptyArray_thenThrowIllegalArgumentException() {
|
||||||
|
final int noRotation = 0;
|
||||||
|
final int someRotation = arr.length - 1;
|
||||||
|
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> bruteForce(arr, noRotation));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> withExtraArray(arr, noRotation));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> cyclicReplacement(arr, noRotation));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> reverse(arr, noRotation));
|
||||||
|
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> bruteForce(null, someRotation));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> withExtraArray(null, someRotation));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> cyclicReplacement(null, someRotation));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> reverse(null, someRotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseBruteForceRotationLtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
bruteForce(arr, rotationLtArrayLength);
|
||||||
|
assertArrayEquals(ltArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseBruteForceRotationGtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
bruteForce(arr, rotationGtArrayLength);
|
||||||
|
assertArrayEquals(gtArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseBruteForceRotationEqArrayLength_thenDoNothing() {
|
||||||
|
int[] expected = arr.clone();
|
||||||
|
|
||||||
|
bruteForce(arr, arr.length);
|
||||||
|
assertArrayEquals(expected, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseExtraArrayRotationLtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
withExtraArray(arr, rotationLtArrayLength);
|
||||||
|
assertArrayEquals(ltArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseExtraArrayRotationGtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
withExtraArray(arr, rotationGtArrayLength);
|
||||||
|
assertArrayEquals(gtArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseExtraArrayWithRotationEqArrayLength_thenDoNothing() {
|
||||||
|
int[] clone = arr.clone();
|
||||||
|
|
||||||
|
withExtraArray(arr, arr.length);
|
||||||
|
assertArrayEquals(clone, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseCyclicReplacementRotationLtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
cyclicReplacement(arr, rotationLtArrayLength);
|
||||||
|
assertArrayEquals(ltArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseCyclicReplacementRotationGtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
cyclicReplacement(arr, rotationGtArrayLength);
|
||||||
|
assertArrayEquals(gtArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseCyclicReplacementRotationEqArrayLength_thenDoNothing() {
|
||||||
|
int[] clone = arr.clone();
|
||||||
|
|
||||||
|
cyclicReplacement(arr, arr.length);
|
||||||
|
assertArrayEquals(clone, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseReverseRotationLtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
reverse(arr, rotationLtArrayLength);
|
||||||
|
assertArrayEquals(ltArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseReverseRotationGtArrayLength_thenRotateArrayOk() {
|
||||||
|
|
||||||
|
reverse(arr, rotationGtArrayLength);
|
||||||
|
assertArrayEquals(gtArrayLengthRotation, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenInputArray_whenUseReverseRotationEqArrayLength_thenDoNothing() {
|
||||||
|
|
||||||
|
int[] clone = arr.clone();
|
||||||
|
|
||||||
|
reverse(arr, arr.length);
|
||||||
|
assertArrayEquals(clone, arr);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user