有没有一种方法可以将向量分成适当的奇数和偶数?

时间:2020-04-06 17:54:21

标签: rust

是否有找到所有偶数并将它们全部移到向量末尾的简便方法?顺序并不重要,重要的是将偶数移到末尾。但是,如果保留订单,那将是

例如:[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),但是如果要在一个操作中执行此操作可能)

1 个答案:

答案 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中的分区步骤。