我想删除向量v2
中与其他向量v1
中的元素匹配的元素,其中v1
中的每个元素在v2
中都有对应的元素但不是反之亦然。
我的想法是像这样使用std::vector::erase
,std::remove_if
和std::find
:
std::vector<int> v1{ 6, 2, 4 };
std::vector<int> v2{ 8, 2, 9, 4, 5, 3, 7, 1, 6 };
v2.erase(
std::remove_if(v2.begin(), v2.end()
, [&v1](auto& item)
{
return std::find(v1.begin(), v1.end(), item) != v1.end();
})
);
哪个有效。但是,我想知道我是否可以在没有匹配已经匹配的那些匹配的情况下进行,因为从v1 -> v2
开始这是一个1:1的关系。 v1
之后会被吹走,所以可以修改它。
答案 0 :(得分:4)
排序v1。使用std equal range来查找其中的元素。将它与你的删除 - 擦除成语代码(带有错误修复)一起使用。
这是O((M + N)lg N)
std::sort( v1.begin(), v1.end() );
auto removed=std::remove_if(
v2.begin(), v2.end(),
[&v1](auto& item)
{
auto r= std::equal_range(v1.begin(), v1.end(), item);
return r.first!=r.second;
}
);
v2.erase(removed, v2.end());
请注意,您在擦除调用中忘记了.end
,这是执行删除擦除时常见的严重错误。
如果您有合理数量的条目,编辑源向量以消除元素是不值得的,除非有极其奇特的数据结构。
答案 1 :(得分:1)
您可以实现线性复杂性来解决您的问题,但需要额外的内存。您可以将第一个向量传递给hash(unordered_set)。因此,您可以获得O(N)复杂度(不包括创建哈希的努力)
std::vector<int> v1{ 6, 2, 4 };
std::vector<int> v2{ 8, 2, 9, 4, 5, 3, 7, 1, 6 };
std::unordered_set<int> hash_v1( v1.begin(), v1.end() );
// linear complexity for remove_if
v2.erase( std::remove_if( v2.begin(), v2.end(), [&hash_v1] ( auto& item )
{
return hash_v1.find( item ) != hash_v1.end(); // constant time
}), v2.end());
不要忘记 v2.end()作为easy方法的第二个参数。
答案 2 :(得分:0)
如果允许您修改v1
,则可以使用以下内容:
v2.erase(
std::remove_if(v2.begin(), v2.end(),
[&v1](auto& item) {
auto it = std::find(v1.begin(), v1.end(), item);
if (it != v1.end()) {
v1.erase(it);
return true;
}
return false;
}
), v2.end());
编辑1:先排序v1
,然后使用std::lower_bound
获取O(log n)搜索速度,而不是O(n)。
修改2 将v1
个元素存储到std::unordered_set
进行删除,然后找到O(1)摊销。
编辑3 :添加了有关Yakk所提及的erase
的错误修正。