将一系列已排序的元素划分为相邻组
partitioning a range of sorted elements into adjacent groups
我在下面有一个排序的项目列表。 我需要确定如何从此列表中选择 [包含、排除(项目对,以便它们之间的差异超过某个固定值(例如以下示例中的 5(。
因此,这应该导致将列表划分为相邻的范围(不遗漏任何元素(。
我想出了一种蛮力方法来做到这一点(参见现场 COLIRU 演示(,但我相信一定有一个更优雅的解决方案,而且我可能错过了一些边缘情况(例如 1 包含单个值的列表应该导致空对(。 我在想 stl 范围算法、std::adjacent_find
或std::lower_bound/std::upper_bound
的组合可以用来确定这些包含/排除对 - 例如在循环中使用或某种基于范围的搜索或某种排序 - 但我无法弄清楚。
实时搜索值{ 100, 104, 108, 112, 116, 120 }
,从而产生以下非重叠范围。 请注意,最后一对(差值为 4(即 <5(是一种特殊情况(请参阅代码(。
[100,104),[108,112),[116,120)
执行此操作的代码如下:
#include <iostream>
#include <algorithm>
#include <experimental/iterator>
#include <string>
#include <vector>
int main()
{
std::vector<int> elements = { 100, 104, 108, 112, 116, 120 };
std::vector<std::pair<int, int>> result;
auto current = elements.begin();
while (current != std::prev(elements.cend())) {
auto next = std::next(current);
while (((*next - *current) < 5) && (next != std::prev(elements.cend()))) {
++next;
}
// consider edge case where we are at the end of the list
if (next != std::prev(elements.cend())) {
result.emplace_back(*current, *std::prev(next));
} else {
result.emplace_back(*current, *next);
}
current = next;
}
std::transform( result.cbegin(), result.cend(), std::experimental::make_ostream_joiner(std::cout, ","),
[](const auto& next){ return std::string("[") + std::to_string(next.first) + ',' + std::to_string(next.second) + ')'; } );
}
auto next = std::next(current);
while (((*next - *current) < 5) && (next != std::prev(elements.cend()))) {
++next;
}
在排序列表中,我们正在寻找比当前元素至少大 5个的第一个元素,对吗?这正是std::lower_bound
的用途 - 它执行二进制搜索而不是线性搜索:
auto next = std::lower_bound(std::next(current), elements.end(), *current + 5);
将其与修复循环条件相结合,直到列表的末尾而不是结束之前(这只是......看起来不对劲,需要一些严肃的理由(,整个身体可以只是:
while (current != elements.end()) {
auto next = std::lower_bound(std::next(current), elements.end(), *current + 5);
result.emplace_back(*current, *std::prev(next));
current = next;
}
<小时 />旁注。这:
std::transform( result.cbegin(), result.cend(), std::experimental::make_ostream_joiner(std::cout, ","),·
[](const auto& next){ return std::string("[") + std::to_string(next.first) + ',' + std::to_string(next.second) + ')'; } );
对我来说,似乎没有比这个更好的了:
bool first = true;
for (auto const& [first, second] : result) {
if (!first) std::cout << ',';
first = false;
std::cout << '[' << first << '',' << second << ']';
}
扬子晚报.我知道人们喜欢说"没有原始循环",但我很少看到transform
导致可读的代码......
相关文章:
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用strcpy将char数组的元素复制到另一个数组
- 使用不带参数的函数访问结构元素
- 给定n个元素的m个集合.在C++中找到出现在最大集合数中的元素
- C++如何通过用户输入删除列表元素
- lower_bound()返回最后一个元素
- 基于多个条件处理地图中的所有元素
- 调整大小后指向元素值的指针unordered_map有效?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 使用函数"remove"删除重复元素
- 具有最大子序列大小的序列,每个元素都相同
- 将一系列已排序的元素划分为相邻组
- c++中向量中元素的划分
- 一个数组可以划分的最大子数组,使得不同子数组中任意两个元素的 GCD 始终为 1?
- 删除每个元素可以将数组中的另一个元素划分
- Valarray划分其元素
- 将字符串划分为结构中的元素
- 将容器中的每个元素划分为给定的数(c++)
- 根据条件划分数组中的元素