BAEL-6913 - Rotate array in java (#14861)

* feat: rotate array in java

* fix: When to when
This commit is contained in:
lucaCambi77 2023-10-11 03:35:10 +02:00 committed by GitHub
parent daaefb0f26
commit d5b2f61ea0
2 changed files with 226 additions and 0 deletions

View File

@ -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");
}
}

View File

@ -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);
}
}