从另一个c ++中删除1个列表中出现的所有元素

时间:2012-05-29 20:35:01

标签: c++ list

假设我有两个列表,l1和l2。我想执行l1 - l2,它返回l1,其中任何元素也是l2的元素被删除。

我可以想到一个简单的循环方法来做到这一点,但这将是非常低效的。在c ++中这样做的有效方法是什么?

举个例子,如果我有l1 = [1,2,6,8]和l2 = [2,8],l1 - l2应该返回[1,6]

谢谢你们

4 个答案:

答案 0 :(得分:2)

您可以使用哈希集以分摊的线性时间执行此操作。

首先,创建一个空集,H。循环L1并将每个元素插入H。

然后,循环通过L2。对于L2的每个元素,当且仅当该元素不在H中时才附加到向量。

如果H提供恒定时间插入和访问,并且您使用常量时间附加结构来存储临时结果,则整体算法在列表大小的总和中是线性的。

答案 1 :(得分:2)

订单是否重要?该列表是否包含重复项?

如果不是,我建议你做set_difference

但是,如果您确实有重复项,我认为set_difference仅删除您要删除的重复元素的第一个匹配项。

答案 2 :(得分:1)

天真的方法需要O(n^2),因为你必须将第一个列表中的每个元素与第二个列表中的每个元素进行比较。

稍微好一点的方法是对列表(O(n*log(n)))进行排序,然后迭代它们。如果对它们进行排序,则只需要一次通过,因此时间为O(n*log(n))

更好的方法是在std::unordered_setO(n))中插入第二个列表的所有元素,迭代第一个列表(O(n))的每个元素并检查如果它包含在集合中(O(1)摊销时间)。这应该做到这一点。 - 只有在没有重复项时才有效。

答案 3 :(得分:0)

如果你想对未分类的情况采用O(n ^ 2)天真的方法,你可以用一点<algorithm>std::bind来做到这一点(或者如果那不是一个选项则提升)诡计:

#include <list>
#include <algorithm>
#include <iostream>
#include <functional>
#include <iterator>

int main() {
  std::list<std::string> a = {"foo", "bar", "baz", "woof"},
                         b = {"baz", "bar", "random other thing"};

  a.erase(std::remove_if(a.begin(), a.end(), std::bind(std::equal_to<std::list<std::string>::iterator>(), b.end(), std::bind(std::find<std::list<std::string>::iterator, std::string>, b.begin(), b.end(), std::placeholders::_1))), a.end());

  std::copy(a.begin(), a.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}