Самое простое решение - отсортировать вектор с помощью специального ключа сортировки:
pub fn sort_by_parity(nums: &mut [i32]) {
nums.sort_by_key(|&x| x % 2 == 0);
}
Стандартный алгоритм сортировки Rust стабилен, поэтому при этом будет сохранен исходный порядок нечетных и четных чисел.
Закрытие, переданное для создания ключей сортировки, оценивается как false
для нечетных чисел и true
для четных чисел. Это гарантирует, что все нечетные числа будут отсортированы перед четными числами.
Вместо того, чтобы принимать изменяемую ссылку на вектор, эта функция принимает изменяемую ссылку на фрагмент, который более обобщенный c.
Время выполнения этого подхода - O (n log n), что не является оптимальным для разделения на месте. Вы можете достичь линейного времени выполнения O (n), например, используя метод partition()
:
pub fn partition_by_parity(nums: &mut [i32]) {
let (even, odd): (Vec<_>, Vec<_>) = nums.iter().partition(|&x| x % 2 == 0);
nums[..odd.len()].copy_from_slice(&odd);
nums[odd.len()..].copy_from_slice(&even);
}
Разница во времени выполнения между двумя подходами на практике вряд ли имеет значение.
Если вам не требуется сохранять исходный порядок нечетных и четных элементов, вы можете разделить срез на месте за линейное время, не требуя дополнительного буфера. Rust Nightly предлагает нестабильный метод partition_in_place()
для этой цели, но это не так уж сложно реализовать самостоятельно - это в основном шаг разделения в Quicksort.