Используйте Fisher–Yates: идите с конца и меняйте элемент i со случайным элементом от 0 до i включительно. Чтобы тесты не меняли общий INPUT_VALUES, перемешивайте копию.
Случайная перестановка элементов массива
Используйте Fisher–Yates: идите с конца и меняйте элемент i со случайным элементом от 0 до i включительно. Чтобы тесты не меняли общий INPUT_VALUES, перемешивайте копию.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Дан массив, содержащий ровно десять целых чисел. Требуется перемешать его элементы в произвольном порядке, аналогично перемешиванию колоды карт.
Решение должно проходить проверку, которая убеждается в следующем:
- После перемешивания массив не является пустым.
- Размер массива остаётся тем же самым.
- В массиве присутствуют все исходные значения, но их порядок может измениться.
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ArraysTest {
private static final int[] INPUT_VALUES = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
@Test
void shouldNotRetrieveEmpty() {
assertThat(Arrays.shuffle(INPUT_VALUES)).isNotEmpty();
}
@Test
void shouldContainSameLength() {
assertThat(Arrays.shuffle(INPUT_VALUES).length).isEqualTo(10);
}
@Test
void shouldContainSameValuesInAnyOrder() {
assertThat(Arrays.shuffle(INPUT_VALUES)).containsExactlyInAnyOrder(INPUT_VALUES);
}
}
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ArraysTest {
private static final int[] INPUT_VALUES = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
@Test
void shouldNotRetrieveEmpty() {
assertThat(Arrays.shuffle(INPUT_VALUES)).isNotEmpty();
}
@Test
void shouldContainSameLength() {
assertThat(Arrays.shuffle(INPUT_VALUES).length).isEqualTo(10);
}
@Test
void shouldContainSameValuesInAnyOrder() {
assertThat(Arrays.shuffle(INPUT_VALUES)).containsExactlyInAnyOrder(INPUT_VALUES);
}
}
Ответ
Используйте Fisher–Yates: идите с конца и меняйте элемент i со случайным элементом от 0 до i включительно. Чтобы тесты не меняли общий INPUT_VALUES, перемешивайте копию.
public final class Arrays {
public static int[] shuffle(int[] input) {
int[] result = input.clone();
var random = java.util.concurrent.ThreadLocalRandom.current();
for (int i = result.length - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
int tmp = result[i];
result[i] = result[j];
result[j] = tmp;
}
return result;
}
}
Это свой класс Arrays, не java.util.Arrays. Время O(n), память O(n) из-за копии. Исходный порядок может случайно сохраниться — это допустимая перестановка. Для криптографических задач нужен другой источник случайности.