是否有找到所有偶数并将它们全部移到向量末尾的简便方法?顺序并不重要,重要的是将偶数移到末尾。但是,如果保留订单,那将是好。
例如:[1, 2, 3, 4, 5]
=> [1, 3, 5, 2, 4]
我想要签名pub fn move_by_filter(nums: &mut Vec<i32>)
。
我试图过滤和组合矢量切片,但是在组合数组切片时遇到了问题:
let evens = nums.iter().filter(|&&i| i % 2 == 0).collect::<Vec<_>>();
let odds = nums.iter().filter(|&&i| i % 2 != 0).collect::<Vec<_>>();
// then I want to do something like: nums = odds.push(evens)
这不会push
到向量的结尾。
我不确定这是否是最好的方法,因为我必须两次使用iter()
(我认为是O(N)+ O(N),但是如果要在一个操作中执行此操作可能)
答案 0 :(得分:5)
最简单的解决方案是使用自定义排序键对向量进行排序:
pub fn sort_by_parity(nums: &mut [i32]) {
nums.sort_by_key(|&x| x % 2 == 0);
}
Rust的标准排序算法很稳定,因此可以保留奇数和偶数的原始顺序。
传递给创建排序键的闭包对于奇数评估为false
,对于偶数评估为true
。这样可以确保所有奇数都排在偶数之前。
此函数不接受对矢量的可变引用,而是接受更通用的可变切片引用。
此方法的运行时间为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中的分区步骤。