我有两个容器std::set
和std::vector
,我的任务是返回std::vector
中std::set
中存在的元素。实现它的最有效方法是什么?
简单方案:
迭代向量元素并在每个元素上调用set.find
,然后在vector.erase
调用,如果没有找到。
答案 0 :(得分:2)
如何寻找每个元素?如果你的矢量没有排序,那么n log(n)
#include <algorithm>
std::vector<int> result;
for(auto&& el: myvector) {
auto it_found = myset.find(el);
if(it != myset.end())
result.push_back(*it_found);
}
现在result
包含两者中的所有元素。
PS:Haven没有编译代码,可能会有轻微的错误。
答案 1 :(得分:0)
最短路可能是使用std::set_intersection
。但是你应该对矢量进行排序以使其工作:
int main()
{
std::set<int> s{1,2,3,4,5,6,7,8};
std::vector<int> v{7,5,10,9};
std::sort(v.begin(), v.end()); // should not bother you if vector is small
std::vector<int> intersection;
std::set_intersection(s.begin(), s.end(), v.begin(), v.end(), std::back_inserter(intersection));
for(int n : intersection)
std::cout << n << ' ';
}
打印:5 7
答案 2 :(得分:0)
根据集合和向量的相对大小,remove_if可能是正确的...
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
std::set<int> s{1,2,3,4,5,6,7,8};
std::vector<int> v{7,5,10,9};
v.erase(std::remove_if(v.begin(), v.end(), [&](int e){return s.count(e) == 0;}), v.end());
for(int n : v)
std::cout << n << ' ';
}
答案 3 :(得分:0)
您可以使用更多STL:)
#include <algorithm>
#include <set>
#include <vector>
#include <iostream>
#include <iterator>
int main() {
std::vector<int> v {5, 4, 3, 2, 1};
std::set<int> s {1, 3, 5};
v.erase(std::remove_if(v.begin(), v.end(),
[&s](int a) { return s.find(a) == s.end(); }),
v.end());
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
}
答案 4 :(得分:0)
如果你在复杂性方面寻找最多的 cpu - 有效的方法,有额外的内存和良好的哈希函数,你可以在O中做到这一点(n + m):
std::vector<int> v;
std::set<int> s;
std::unordered_set<int> us{s.cbegin(), s.cend(), s.size()};
v.erase(
std::remove_if(v.begin(), v.end(),
[&us] (const int entry) { return us.find(entry) == us.cend(); }),
v.end());
说明:您迭代set
一次(O(m))以准备unordered_set
。然后,您遍历vector
一次(O(n)),每步执行unordered_set::find
(0(1))。它为您提供了O(n + m)的复杂性。
此外,unordered_set
的大小等于set
的大小和良好的哈希函数有助于减少std::unordered_set::find
复杂度的不变部分。
请参阅live example。
但请记住,较低的复杂性并不一定意味着在特定情况下执行速度更快(例如,由于额外的分配)。