如何删除向量中与另一个向量中的某个元素匹配的元素

时间:2017-12-07 17:02:36

标签: c++ c++11 visual-c++ c++14

我想删除向量v2中与其他向量v1中的元素匹配的元素,其中v1中的每个元素在v2中都有对应的元素但不是反之亦然。

我的想法是像这样使用std::vector::erasestd::remove_ifstd::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之后会被吹走,所以可以修改它。

3 个答案:

答案 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的错误修正。