首先,我认为这个问题需要改进,因为它非常不清楚。
不过,我会尝试推测。
我有一个相等的偶数和奇数整数数组。
基于此,由于偶数和奇数不能相等,我假设您想说您有相同数量的偶数和奇数,例如 3 个奇数和3 个偶数,如输入 [1, 2, 3, 4, 5, 6] 的情况。
另一方面,我认为示例[1, 2, 3, 4, 5, 6] 不够通用,因为一个奇偶校验的每个整数已经在另一个奇偶校验的两个连续整数之间,所以解决方案是交换前两个元素,发送两个元素,第三个两个元素,依此类推。
一个稍微更一般的例子是[1, 2, 5, 3, 10, 8],它应该变成[2, 1, 8, 3, 10, 5]。
要做到这一点,一种策略是
- 对向量/列表/任何内容进行分区,使所有偶数占据左侧,所有奇数占据右侧 (
[2,10,8,1,5,3]),
- 对两个分区进行独立排序 (
[2,8,10,1,3,5]),
- 将它们压缩到 2 范围内 (
[[2,1],[8,3],[10,5]])
- 连接这些范围 (
[2,1,8,3,10,5])
您可以使用 Range-v3 轻松做到这一点,它几乎就像上面的列表一样:
#include <iostream>
#include <range/v3/action/sort.hpp>
#include <range/v3/algorithm/partition.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/join.hpp>
#include <range/v3/view/single.hpp>
#include <range/v3/view/take.hpp>
#include <range/v3/view/zip_with.hpp>
#include <vector>
using ranges::partition;
using namespace ranges::actions;
using namespace ranges::views;
int main(){
std::vector<int> v{1, 2, 5, 3, 10, 8};
auto constexpr is_even = [](int i){ return i % 2 == 0; };
auto constexpr make_range_of_2 = [](int x, int y){
return concat(single(x), single(y));
};
partition(v, is_even); // partition
auto r = zip_with(make_range_of_2,
sort(v | take(v.size()/2)/* even integers */),
sort(v | drop(v.size()/2)/* odd integers */))
| join/* range-or-ranges -> range */;
for (auto i : r) {
std::cout << i << std::endl;
}
}
考虑到一半的代码是#includes 和usings,解决方案相当简洁。
让我们再看一遍,vs 英文:
- 我们
partition集合v使得所有偶数都排在所有奇数之前,
partition(v, is_even);
- 我们
zip_with函数make_range_of_2...
auto r = zip_with(make_range_of_2,
- ...
sorted 前半部分的v 范围(偶数)...
sort(v | take(v.size()/2)),
- ... 和
sorted 的后半部分v(奇数)的愤怒,
sort(v | drop(v.size()/2)))
- 最后我们将
join 与zip_with 得到的所有“配对”放在一个大范围内
| join;
它解释了自己!
也许不太清楚的部分是make_range_of_2 的实现。我们需要的是一个给定两个ints 的函数,它返回一个只包含这两个的范围。我不知道是否有更简单的方法,但我能想到的第一个方法是通过single 从每个int 中创建一个元素范围,然后concatenating 它们。