C ++,快速从另一个向量唯一的向量中删除元素

时间:2012-01-23 22:43:21

标签: c++ vector unique

有2个未分类的int和vector对象的向量int,int

std::vector <int> v1;
std::vector <std::pair<int, float> > v2;

包含数百万件物品。

如何尽可能快地从v1中删除这些v2.first独有的项目(即不包含在v2.first中)?

示例:

v1:  5 3 2 4 7 8
v2: {2,8} {7,10} {5,0} {8,9}
----------------------------
v1: 3 4

2 个答案:

答案 0 :(得分:6)

我会尽快使用两种技巧来做到这一点:

  1. 使用某种关联容器(可能是std::unordered_set)来存储第二个向量中的所有整数,以便查找是否应该删除第一个向量中的某个整数。

  2. 优化从初始向量中删除元素的方式。

  3. 更具体地说,我会做以下事情。首先创建一个std::unordered_set并添加第二个向量中该对中第一个整数的所有整数。这给了(预期的)O(1)查找时间来检查集合中是否存在特定的int

    现在您已经这样做了,使用std::remove_if算法删除哈希表中存在的原始vector中的所有内容。您可以使用lambda来执行此操作:

    std::unordered_set<int> toRemove = /* ... */
    v1.erase(std::remove_if(v1.begin(), v1.end(), [&toRemove] (int x) -> bool {
        return toRemove.find(x) != toRemove.end();
    }, v1.end());
    

    将所有内容存储在unordered_set中的第一步需要预期的O(n)时间。第二步通过将所有删除聚集到最后并使查找花费很少时间来完成预期的O(n)工作。这给出了整个过程的预期O(n) - 时间,O(n)空间的总和。

    如果允许对第二个向量(对)进行排序,那么您可以在O(n log n)最坏情况时间,O(log n)最坏情况空间中通过对向量进行排序来执行此操作密钥,然后使用std::binary_search检查是否应删除第一个int中的特定vector。每个二进制搜索需要O(log n)时间,因此所需的总时间为排序的O(n log n),第一个向量中每个元素的O(log n)时间(总计为O(n log n)) )和O(n)删除时间,总共给出O(n log n)。

    希望这有帮助!

答案 1 :(得分:1)

假设两个容器都没有排序,而且排序实际上太贵或者内存不足:

v1.erase(std::remove_if(v1.begin(), v1.end(), 
                        [&v2](int i) { 
                         return std::find_if(v2.begin(), v2.end(), 
                                             [](const std::pair<int, float>& p) { 
                                                return p.first == i; }) 
                                != v2.end() }), v1.end());

或者在v2上对first进行排序,然后使用二进制搜索。如果内存足够,请使用unordered_setfirst v2进行排序。

完整的C ++ 03版本:

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>

struct find_func {
  find_func(int i) : i(i) {}

  int i;
  bool operator()(const std::pair<int, float>& p) {
    return p.first == i;
  }
};

struct remove_func {
  remove_func(std::vector< std::pair<int, float> >* v2) 
  : v2(v2) {}
  std::vector< std::pair<int, float> >* v2;
  bool operator()(int i) {
    return std::find_if(v2->begin(), v2->end(), find_func(i)) != v2->end();
  }
};


int main()
{
  // c++11 here
  std::vector<int> v1 = {5, 3, 2, 4, 7, 8};
  std::vector< std::pair<int, float> > v2 = {{2,8}, {7,10}, {5,0}, {8,9}};
  v1.erase(std::remove_if(v1.begin(), v1.end(), remove_func(&v2)), v1.end());

  // and here
  for(auto x : v1) {
    std::cout << x << std::endl;
  }

  return 0;
}