【问题标题】:How to get the difference of two vectors A - B如何获得两个向量 A - B 的差异
【发布时间】:2020-09-09 00:20:34
【问题描述】:

如何使用向量 A 和向量 B 在 C++ 中找到集合之间的差异。我想出了联合和交集,但由于某种原因,无论我尝试什么都无法得到差异。任何帮助将不胜感激(顺便说一句,我需要手动完成,而不是使用内置方法。)

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm>

using namespace std;

void Difference();

int main()
{
    Difference();

    return 0;
}


void Difference()
{
    int temp = 0;
    vector<int> D{};
    vector<int> A{3, 4, 9, 12, 13, 15};

    vector<int> B{1, 3, 5, 7, 9};

    for(int i = 0; i < A.size(); i++)
    {
        for (int j = 0; j < B.size(); j++)
        {

            if (A[i] != B[j])
            {
                int temp = A[i];
                D.push_back(temp);
            }


                  //Used To Sort The Vector So There Is No Duplicates And Its In Order!
                  sort( D.begin(), D.end() );
                  D.erase( unique( D.begin(), D.end() ), D.end() );
        }

    }
    cout << "Difference: ";
    for(int z = 0; z < D.size(); z++)
    {
        cout << D[z] << " ";
    }
}

【问题讨论】:

  • 有示例实现here.
  • 很抱歉应该指定我需要手动完成,而不是使用已经实现的东西。
  • 我了解,但该页面有 2 个可能的实现版本。您可以从那里为您的代码获取一些灵感。
  • 因为有了交叉点,你只需要找到不在交叉点的元素

标签: c++ vector set-operations


【解决方案1】:
if (A[i] != B[j])
{
    int temp = A[i];
    D.push_back(temp);
}

您应该意识到这会将A[i] 添加到A[i] 不等于B每个元素 的向量D 中。因此,除非B 仅包含相同的元素,否则A 中的所有内容都会传递到D。更详细地说,{3, 4, 9} - {1, 3} 操作将:

  • 添加一次3(因为它不等于1);
  • 两次添加4(因为它既不等于1也不等于3);和
  • 添加两次9(因为它既不等于1也不等于3)。

因此,在删除重复后,您最终会得到 {3, 4, 9},尽管事实上 3 在两个向量中。


您需要做的是检查 any 元素是否匹配,而不是像当前代码那样检查 每个 元素。这可以通过以下循环来完成:

// For each element in A.

for(size_t i = 0; i < A.size(); i++) {
    // Start by assuming not in B, then check every B.

    bool contains = false;
    for (size_t j = 0; j < B.size(); j++) {
        // If found in B, exit early and save that fact.

        if (A[i] == B[j]) {
            contains = true;
            break;
        }
    }

    // If it was not found in B, add it to D.

    if (! contains) {
        int temp = A[i];
        D.push_back(temp);
    }
}

这样,您也不必不必担心重复删除,除非原始向量中有重复项。如果是这种情况,您可能需要在原始算法(和这个算法)中增加一些智能来处理(例如){1, 2, 3, 3, 3}{3} 之间的差异。也就是说,应该是{1, 2}还是{1, 2, 3, 3}

【讨论】:

  • 这有 O(n^2) 运行时间。使用 unordered_map 使其成为 O(n)?
  • @SilverFlash,原始问题使用向量并且具有时间复杂度,我不确定您如何建议将其转换为地图,而不是将每个向量元素映射到人为创建的值。是的,它们是您可以对代码进行的根本性更改,以提高效率(例如,在向量很大的情况下),但我的目的是回答所提出的问题。
【解决方案2】:
#include <algorithm>
#include <iostream>
#include <vector>

void sort_and_unique(std::vector<int> &vec) {
  std::sort(vec.begin(), vec.end());
  vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
}

std::vector<int> difference(std::vector<int> a, std::vector<int> b) {
  sort_and_unique(a);
  sort_and_unique(b);
  std::vector<int> res;
  size_t left = 0, right = 0;
  while (left < a.size() && right < b.size()) {
    if (a[left] < b[right]) {
      res.emplace_back(a[left++]);
    } else if (a[left] == b[right]) {
      left++;
      right++;
    } else {
      right++;
    }
  }
  while (left < a.size()) {
    res.emplace_back(a[left++]);
  }
  return res;
}

int main() {
  std::vector<int> A{3, 4, 9, 12, 13, 15};
  std::vector<int> B{1, 3, 5, 7, 9};
  std::vector<int> res = difference(A, B);
  for (int x : res) {
    std::cout << x << ' ';
  }
  std::cout << std::endl;
  return 0;
}

这是一个O(nlogn) 方法,它也删除重复元素。关键是要利用排序。使用双指针方法可以帮助实现。

如果输入可靠(每个元素在其自己的向量中都是唯一的),则可以省略 vec.erase 行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多