问题>给定两个排序的数组A和B,返回一个包含A和B共有元素的数组C.数组C不能包含重复项。
这是我的解决方案,但我的预感是它错了。但我无法找到反驳它的反例。 有人可以为我指出它吗?或者给我一个反例?
更新
该算法的工作原理如下:
我们持有一个指向每个数组的指针并向前移动这些指针,直到找到一个公共元素。然后,如果公共元素不在C中,则找到的元素存储在C中。否则,依赖于元素,我们相应地向前移动指针。
#include <iostream>
#include <vector>
#include <random>
#include <iterator>
#include <algorithm>
using namespace std;
vector<int> Intersect(const vector<int>& vecIntsA, const vector<int>& vecIntB)
{
int indA = 0;
int indB = 0;
vector<int> vecIntC;
while(indA < vecIntsA.size() && indB < vecIntB.size())
{
if (vecIntsA[indA] == vecIntB[indB]) {
if ( vecIntC.empty() || vecIntC.back() != vecIntsA[indA])
vecIntC.emplace_back(vecIntsA[indA]);
indA++;
indB++;
} else if (vecIntsA[indA] < vecIntB[indB])
indA++;
else // (vecIntsA[indA] > vecIntB[indB])
indB++;
}
return vecIntC;
}
int main()
{
default_random_engine dre;
uniform_int_distribution<int> dist(0, 100);
vector<int> vecIntA;
for(int i=0; i < 20; ++i)
vecIntA.emplace_back(dist(dre));
sort(vecIntA.begin(), vecIntA.end());
copy(vecIntA.cbegin(), vecIntA.cend(), ostream_iterator<int>(cout, ","));
cout << endl;
vector<int> vecIntB;
for(int i=0; i < 24; ++i)
vecIntB.emplace_back(dist(dre));
sort(vecIntB.begin(), vecIntB.end());
copy(vecIntB.cbegin(), vecIntB.cend(), ostream_iterator<int>(cout, ","));
cout << endl;
vector<int> vecIntC = Intersect(vecIntA, vecIntB);
copy(vecIntC.cbegin(), vecIntC.cend(), ostream_iterator<int>(cout, ","));
return 0;
}
答案 0 :(得分:1)
你总是可以使用STL算法set_intersection和unique?
答案 1 :(得分:0)
你的算法看似合理。为了它的价值,我最近解决了完全相同的问题,并在两个数组具有相似长度的情况下提出了a similar algorithm。
一般而言,如果您希望支持您的算法产生良好解决方案的信念,请以您可以自动检查的方式表达优秀解决方案的基本属性。然后针对这些属性编写自动化测试。 (这是QuickCheck普及的一种很好的测试方式。)
对于这个问题,例如,我表达了数组交集的基本属性,如下所示:“给定交集函数f
,对于所有已排序的数组A
和B
,{{ 1}}“。 (在Python中,f(A, B) == sorted(set(A) & set(B))
从set(xs)
的元素生成一个集合,应用于集合的xs
运算符计算交集。)本质上,我将所需的数组交集语义映射到Python的用于排序和集合交集的内置语义。这样,我就可以通过便宜,易于获得的部件为我的实现建立一个正确的oracle。最后一步是构建随机测试用例并检查是否(通过咨询oracle)为所有这些测试提供了映射。
以下是相应的代码:
&
答案 2 :(得分:0)
这是一个时间复杂度(p + q)的快速解决方案,其中p和q分别是数组A和B的长度。
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
set<int> intersect(vector<int> &A, vector<int> &B) {
int j = 0;
vector<int> V;
for(int i = 0;i<A.size();i++){
first:
if(j == B.size()) break;
if(A[i] == B[j]){
V.push_back(A[i]);
j++;
}
else if(A[i]>B[j]) { j++;goto first;}
}
set<int> S(V.begin(), V.end());
return S;
}
int main() {
vector<int> A,B;
A = {1,2,3,3,4,5,6};
B = {3,3,5,6};
set<int> S;
S = intersect(A,B);
set<int>::iterator iter;
for(iter=S.begin(); iter!=S.end();++iter){
cout<<(*iter)<<" ";
}
return 0;
}
这是一个2-pointer
解决方案。当其他循环向前移动时,尝试在其中一个循环中寻找单调性。如果您找到了,您就找到了优化。快乐的编码:)