Как реализовать разворот массива inplace без использования стандартных функций
Что проверяют
Базовую работу с индексами и понимание, что значит «in-place»: O(1) дополнительной памяти и изменение исходного массива. Следом спрашивают про сложность, обобщённую версию и то, чем вы бы воспользовались в рабочем коде.
Как отвечать
Алгоритм двух указателей: left с начала, right с конца, меняете элементы местами и сдвигаете указатели навстречу, пока left < right. Получается n/2 обменов, O(n) по времени и O(1) по памяти.
static void Reverse<T>(T[] array)
{
ArgumentNullException.ThrowIfNull(array);
for (int left = 0, right = array.Length - 1; left < right; left++, right--)
(array[left], array[right]) = (array[right], array[left]);
}Что стоит проговорить:
- обмен кортежем: деконструкция доступна с C# 7, компилятор разворачивает её в обычный обмен через временные переменные, аллокаций нет;
- краевые случаи: у пустого массива
rightравен-1, цикл не выполнится ни разу, у массива из одного элемента тоже. Дляnullявное исключение лучше, чемNullReferenceExceptionгде-то внутри; - обобщение: версия с
Tработает для любого типа, а сигнатура соSpan<T>позволит разворачивать и часть массива, и буфер изstackalloc; - почему без
ref: массив это ссылочный тип, метод получает ссылку на тот же объект и меняет его содержимое.refпонадобился бы, только чтобы подменить сам массив.
В рабочем коде вы бы вызвали Array.Reverse(array) или array.AsSpan().Reverse(): они делают то же самое на месте и в современных версиях .NET оптимизированы для примитивных типов. Скажите это, чтобы было видно: цикл вы пишете по условию задачи, а не по незнанию.
Где спотыкаются
Проходят цикл до array.Length вместо середины. Каждая пара меняется дважды, и массив возвращается в исходный вид.
Предлагают Enumerable.Reverse из LINQ или копию в новый массив. Это уже не in-place: создаётся новая последовательность, а исходный массив не меняется.
Меняют местами через XOR ради «экономии переменной». Для целых чисел это работает, пока индексы различны, для других типов не работает вовсе и быстрее не становится.