C++数组交集
C++ Array Intersection
有人知道是否可以将其从O(m*n)转换为O(m+n)吗?
vector<int> theFirst;
vector<int> theSecond;
vector<int> theMatch;
theFirst.push_back( -2147483648 );
theFirst.push_back(2);
theFirst.push_back(44);
theFirst.push_back(1);
theFirst.push_back(22);
theFirst.push_back(1);
theSecond.push_back(1);
theSecond.push_back( -2147483648 );
theSecond.push_back(3);
theSecond.push_back(44);
theSecond.push_back(32);
theSecond.push_back(1);
for( int i = 0; i < theFirst.size(); i++ )
{
for( int x = 0; x < theSecond.size(); x++ )
{
if( theFirst[i] == theSecond[x] )
{
theMatch.push_back( theFirst[i] );
}
}
}
将第一个向量的内容放入哈希集,例如std::unordered_set
。这就是O(m)。扫描第二个矢量,检查这些值是否在undered_set中,并对那些在的值进行计数。这是一个散列结构的n个查找,所以O(n)。因此,O(m+n)。如果重叠中有l个元素,则可以计算将它们添加到第三个向量的O(l)。std::unordered_set
在C++0x草案中,在最新的gcc版本中可用,在boost中也有一个实现。
编辑以使用Undered_set
使用C++2011语法:
unordered_set<int> firstMap(theFirst.begin(), theFirst.end());
for (const int& i : theSecond) {
if (firstMap.find(i)!=firstMap.end()) {
cout << "Duplicate: " << i << endl;
theMatch.push_back(i);
}
}
现在,问题仍然存在,你想如何处理原件中的副本?明确地说,1
应该在theMatch
中有多少次,1次、2次或4次?该输出:
Duplicate: 1
Duplicate: -2147483648
Duplicate: 44
Duplicate: 1
使用此选项:http://www.cplusplus.com/reference/algorithm/set_intersection/
我相信你应该能够达到O(mlogm + nlogn)
。(set_intersection
要求已经对输入范围进行排序)。然而,这可能与针对重复元素的解决方案有点不同。
如果我错了,请纠正我,您正在为交叉口问题建议以下解决方案:对两个向量进行排序,并以我们到达一个公共元素的方式在两个排序的向量中保持迭代,因此总体复杂性(n*log(n)+m*log(m))+(n+m)假设k*log(k)为排序的复杂性
我说得对吗?当然,复杂性将取决于排序的复杂性。
我会对较长的数组O(n*log(n))进行排序,从较短的数组O中搜索元素(m*log(n))。总计为O(n*log(n)+m*log(n))
假设您想从两个数据集生成theMatch
,而不关心数据集本身,请将其中一个放在unordered_map
中(目前可从Boost获得,并在C++11的最终委员会草案中列出),将键映射到一个整数,该整数在添加时会增加,因此可以跟踪键出现的次数。然后,当您在另一个数据集上获得命中时,您push_back
命中第一次发生的次数。
您可以通过首先对向量进行排序来获得O(n log n+m log m),或者通过创建其中一个向量的std::map
来获得O。
注意:这些不是保序操作,theMatch
将以不同的顺序和不同的技术出现。在我看来,这个命令可能被认为是武断的。如果上面代码中给出的顺序是必要的,我认为没有更好的算法了。
编辑:
以类型为type的数据集A和数据集B为例。创建一个unordered_map<Type, int>
。
浏览数据集A,并检查每个成员以查看它是否在地图中。如果没有,请将int
为1的元素添加到映射中。如果是,则递增int
。这些运算中的每一个平均值都是O(1),所以这一步是O(len A)。
浏览数据集B,并检查每个成员,看看它是否在地图中。如果没有,请继续下一个。如果是,则将成员push_back
添加到目标队列中。int
是该值在数据集A中的次数,push_back
也是成员在A中重复给定行为的次数。这些运算中的每一个都是O(1)的平均值,所以这一步是O(len B)。
这是一般行为。如果你总是遇到最坏的情况,你会得到O(m*n)。我认为没有办法保证O(m+n)。
如果结果数组/集合中元素的顺序无关紧要,那么答案是肯定的。
对于任意类型的具有一定阶数的元素,最佳算法是O( max(m,n)*log(min(m,n)) )
。对于有限大小的数字,最好的算法是O(m+n)
。
-
构造较小数组的元素集-对于任意元素,只需排序即可,对于有限大小的数字,它必须类似于数字排序中的中间表
-
遍历较大的数组并检查元素是否在先前构建的集合中——对于任意元素,二进制搜索是OK(即
O(log(min(n,m))
),对于数字,单个检查是O(1)。
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组的地址分配给变量并删除
- 从C++本机插件更新Vector3数组
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 数组索引的值没有增加
- 将对象数组的引用传递给函数
- 为char数组调整zlib-zpipe
- 2D数组来自文本输入,中间有空格
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- 使用strcpy将char数组的元素复制到另一个数组
- 使用指针从C++中的数组中获取最大值
- C++使用整数的压缩数组初始化对象
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '