两个排序数组的相交

时间:2013-10-09 04:08:48

标签: c++ algorithm

问题>给定两个排序的数组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;
}

3 个答案:

答案 0 :(得分:1)

你总是可以使用STL算法set_intersection和unique?

答案 1 :(得分:0)

你的算法看似合理。为了它的价值,我最近解决了完全相同的问题,并在两个数组具有相似长度的情况下提出了a similar algorithm

一般而言,如果您希望支持您的算法产生良好解决方案的信念,请以您可以自动检查的方式表达优秀解决方案的基本属性。然后针对这些属性编写自动化测试。 (这是QuickCheck普及的一种很好的测试方式。)

对于这个问题,例如,我表达了数组交集的基本属性,如下所示:“给定交集函数f,对于所有已排序的数组AB,{{ 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解决方案。当其他循环向前移动时,尝试在其中一个循环中寻找单调性。如果您找到了,您就找到了优化。快乐的编码:)