Случайная перестановка элементов массива

Используйте Fisher–Yates: идите с конца и меняйте элемент i со случайным элементом от 0 до i включительно. Чтобы тесты не меняли общий INPUT_VALUES, перемешивайте копию.

Короткий ответ

Что ответить на собеседовании

Используйте Fisher–Yates: идите с конца и меняйте элемент i со случайным элементом от 0 до i включительно. Чтобы тесты не меняли общий INPUT_VALUES, перемешивайте копию.

Подробный разбор

Ответ с пояснениями

Условие

Дан массив, содержащий ровно десять целых чисел. Требуется перемешать его элементы в произвольном порядке, аналогично перемешиванию колоды карт.

Решение должно проходить проверку, которая убеждается в следующем:

  1. После перемешивания массив не является пустым.
  2. Размер массива остаётся тем же самым.
  3. В массиве присутствуют все исходные значения, но их порядок может измениться.
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) из-за копии. Исходный порядок может случайно сохраниться — это допустимая перестановка. Для криптографических задач нужен другой источник случайности.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее