Как отсортировать массив так, чтобы четные числа остались на своих местах, а нечетные были отсортированы по возрастанию
Что проверяют
Умеете ли вы разложить задачу на простые шаги и не наступить на особенности JavaScript: сортировку по умолчанию и остаток от деления отрицательных чисел. Следом просят оценить сложность и спрашивают, мутирует ли ваша функция исходный массив.
Как отвечать
Сначала проговорите идею, потом пишите код. Нечётные числа собираем отдельно и сортируем, затем проходим исходный массив и подставляем их по порядку туда, где раньше стояли нечётные. Чётные не трогаем.
function sortOdds(arr) {
const odds = arr.filter(n => n % 2 !== 0).sort((a, b) => a - b);
let i = 0;
return arr.map(n => (n % 2 !== 0 ? odds[i++] : n));
}
sortOdds([5, 3, 2, 8, 1, 4]); // [1, 3, 2, 8, 5, 4]Что стоит сказать вслух:
- сложность: проходы
filterиmapдают O(n), сортировка k нечётных O(k log k), итого O(n + k log k), в худшем случае O(n log n). Дополнительная память O(k); - иммутабельность:
filterсоздаёт новый массив, поэтомуsortна нём исходный не портит, аmapвозвращает результат новым массивом. Для сортировки копии без мутации в современных движках естьtoSorted(); - граничные случаи: пустой массив, только чётные, только нечётные, отрицательные числа, ноль (он чётный).
Если спросят про вариант без лишней памяти, можно сортировать нечётные на месте по списку их индексов, но код станет сложнее, а выигрыш на фронтенде редко что-то решает.
Где спотыкаются
Вызывают sort() без компаратора. Он сравнивает элементы как строки, и [10, 9, 1] превращается в [1, 10, 9].
Проверяют нечётность через n % 2 === 1. В JavaScript -3 % 2 равно -1, поэтому отрицательные нечётные числа молча остаются на месте. Надёжнее n % 2 !== 0.
Ищут позицию для замены через indexOf внутри цикла. Это даёт O(n²) и ломается на повторяющихся значениях: второй дубль найдёт позицию первого.