删除两个向量C ++中的相似元素

时间:2018-04-26 20:13:32

标签: c++ loops vector

我正在尝试搜索两个相同元素的向量(每个大小),然后删除这两个元素。

我的实施如下:

for (int i = vec1.size() - 1; i >= 0; i--) {
     for (int j = 0; j < vec2.size(); j++) {
          if (vec1[i] == vec2[j]) {
             vec1.erase(vec1.begin() + i);
             vec2.erase(vec2.begin() + j);
          }
     }
}

然而,虽然这适用于大多数情况,但我遇到了一些它没有的地方。这是我在迭代这些载体的方式还是我只是这样做错了?

4 个答案:

答案 0 :(得分:2)

问题是,在您从vec1[i]vec2删除元素后,当您循环vec1时,您会继续访问vec2。如果在删除vec1中的最后一个元素后执行此操作会导致未定义的行为,因为vec1[i]不再有效。在break中添加if语句即可解决此问题。

for (int i = vec1.size() - 1; i >= 0; i--) {
     for (int j = 0; j < vec2.size(); j++) {
          if (vec1[i] == vec2[j]) {
             vec1.erase(vec1.begin() + i);
             vec2.erase(vec2.begin() + j);
             break; // Look at next element in vec1
          }
     }
}

对于O(n*log(n)+m*log(m)+n+m)O(n*m),还有一种更有效的方法(n=vec1.size()而不是m=vec2.size()。它涉及对载体进行分类。我会留给你弄清楚的。

答案 1 :(得分:2)

实际上你根本不需要向后迭代。在这种情况下,您的代码可以是:

for (int i = 0; i < vec1.size(); i++) {
     for (int j = 0; j < vec2.size(); j++) {
          if (vec1[i] == vec2[j]) {
             vec1.erase(vec1.begin() + i);
             vec2.erase(vec2.begin() + j);
          }
     }
}

但等等......擦掉一个元素后会发生什么?然后它之后的所有元素的索引都减少了1,所以我们将跳过下一个项目!为了解决这个问题,我们可以添加这个小修改:

             vec1.erase(vec1.begin() + i--);
             vec2.erase(vec2.begin() + j--);
                                       ^^^^

即使我们通过擦除来改变大小,这也会起作用,因为我们正在检查vec2每个循环的大小!但是如果我们最终删除vec1的最后一项呢?在我们通过vec2迭代所有之前,我们不会再次比较它的大小,这将是vec1 = {2}, vec2 = {2, 2, 2}示例中的一个问题。为了解决这个问题,我们可以突破内循环并重复检查vec2

把它们放在一起(并将你的下标操作符更改为.at()调用,这样我们就可以检查边界了)你得到:

for (int i = 0; i < vec1.size(); i++) {
     for (int j = 0; j < vec2.size(); j++) {
          if (vec1.at(i) == vec2.at(j)) {
             vec1.erase(vec1.begin() + i--);
             vec2.erase(vec2.begin() + j--);
             break;
          }
     }
}

(请在此处查看:ideone

答案 2 :(得分:1)

如果你可以排序,你可以这样做:

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

int main() {

  std::vector<int> ex {3, 1, 2, 3, 3, 4, 5}, as {2, 3, 6, 1, 1, 1}, tmp;

  std::sort(std::begin(ex), std::end(ex));
  std::sort(std::begin(as), std::end(as));

  as.erase(
    std::remove_if(
      std::begin(as),std::end(as),
      [&](int const& s){
        bool found = std::binary_search(std::begin(ex), std::end(ex), s);
        if (found) {
          tmp.push_back(s);
        }
        return found;}), std::end(as));
  for (auto const& i : tmp) {
    ex.erase(std::remove(std::begin(ex),std::end(ex), i), std::end(ex));
  }

}

答案 3 :(得分:0)

尝试使用std::set_difference从另一个向量中减去一个向量,然后在std::merge的帮助下合并这些减法。但是需要对向量进行排序以使用这些函数,因此首先使用std::sort。代码在这里:

void TraceVector( std::vector<int> v, const std::string& title )
{
    if ( !title.empty() )
    {
        std::cout << title << std::endl;
    }

    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
}

int main() {

    std::vector<int> Vec1 {7, 1, 2, 5, 5, 5, 8, 9};
    std::vector<int> Vec2 {3, 2, 5, 7, 10};
    std::vector<int> Difference1; // Contains subtraction Vec1 - Vec2
    std::vector<int> Difference2;// Contains subtraction Vec2 - Vec1
    std::vector<int> Merged; // RESULT Merged vector after subtractions

    //Need to be sorted
    std::sort(Vec1.begin(), Vec1.end());
    std::sort(Vec2.begin(), Vec2.end());

    TraceVector(Vec1, "Vec1 sorted is: ");
    TraceVector(Vec2, "Vec2 sorted is: ");

    //Make subtractions
    std::set_difference(Vec1.begin(), Vec1.end(), Vec2.begin(), Vec2.end(),
                        std::inserter(Difference1, Difference1.begin()));
    std::set_difference(Vec2.begin(), Vec2.end(), Vec1.begin(), Vec1.end(),
                        std::inserter(Difference2, Difference2.begin()));


    TraceVector(Difference1, "Difference is: ");
    TraceVector(Difference2, "Difference is: ");

    //Merge subtrctions
    std::merge(Difference1.begin(), Difference1.end(), Difference2.begin(), Difference2.end(), back_inserter(Merged));
    TraceVector(Merged, "Merged is: ");
}

输出是:

Vec1 sorted is: 
1,2,5,5,5,7,8,9,
Vec2 sorted is: 
2,3,5,7,10,
Difference is: 
1,5,5,8,9,
Difference is: 
3,10,
Merged is: 
1,3,5,5,8,9,10,
Program ended with exit code: 0