Search code examples
c++algorithmc++11stdvectorunion-find

Count how many different vectors left after union


I'm only using std::vector in this problem and each vector is ordered without duplicate. Now I want to union the vectors that have same numbers. So 2 3 can be union with 3 4 5 but not with 4 5 nor 1 5.

Example:

If I have following vectors...

1
1
2 3 4
5
1 5
2
4 7

After the union I should have only 2 vectors left:

1 5
2 3 4 7

Codes:

vector<int> a,b,c,d,e,f,g;
vector<vector<int>> myList;

a.push_back(1);
b.push_back(1);
c.push_back(2);
c.push_back(3);
c.push_back(4);
d.push_back(5);
e.push_back(1);
e.push_back(5);
f.push_back(2);
g.push_back(4);
g.push_back(7);

myList.push_back(a);
myList.push_back(b);
myList.push_back(c);
myList.push_back(d);
myList.push_back(e);
myList.push_back(f);
myList.push_back(g);

//this should print out the vectors in my above example
for (int i =0; i<myList.size(); i++) {
    for (int j=0; j<myList[i].size(); j++) {
        cout<<myList[i][j]<<" ";
    }
    cout<<endl;
}

I tried to use set_union and set_intersection to achieve my goal but it doesn't work as expected..I suspect the problem is with the size of vector that I'm not changing properly. Please help. Thanks!

EDIT:

This is the buggy code, originally I have problem with union, but just now it works automatically.. Now I think I'm mostly not sure how to use set_intersection to find out whether there's intersection

vector<int>::iterator myIt;
vector<int> myTemp;
vector<int> myTemp2;
vector<int> myResult(20);
vector<int> myResult2(20);


while (!myList.empty()) {

    myTemp2 = myList.back();
    myList.pop_back();


    myIt = set_intersection(myTemp.begin(), myTemp.end(), 
                            myTemp2.begin(), myTemp2.end(), myResult.begin());

    //this is checking whether there is intersection but it doesn't work
    if (myResult.size()) {

        myIt = set_union(myTemp.begin(), myTemp.end(), 
                         myTemp2.begin(), myTemp2.end(), myResult2.begin());

        myTemp = myResult2;

    }


}

cout<<"after union: "<<endl;

for (auto it = myResult2.begin(); it != myResult2.end() ; it++) {
    cout<<*it<< " ";
}

Solution

  • If I understand you correctly, not only your code but your approach is drastically wrong. You are trying to solve a connected components/disjoint sets type problem, but your method for instance only returns a single vector of ints...? It needs to return a vector of vector<int>s surely.

    The following code is the closest thing to yours I can think of which should work. It should leave result with the output you want.

    vector< vector<int> > result;
    
    for(int i = 0; i < myList.size(); i++)
    {
    
        bool match = false;
        int matchFirst = -1;
    
        for(int j = 0; j < result.size(); j++)
        {
    
            vector<int> myResult;
            vector<int> myResult2;
    
            set_intersection(myList[i].begin(), myList[i].end(),
                             result[j].begin(), result[j].end(),
                             back_inserter(myResult));
    
            if (myResult.size())
            {
                set_union(myList[i].begin(), myList[i].end(),
                          result[j].begin(), result[j].end(), back_inserter(myResult2));
    
                if(match)
                {
                    vector<int> myResult3;
                    set_union(myResult2.begin(), myResult2.end(),
                              result[matchFirst].begin(), result[matchFirst].end(), back_inserter(myResult3));
                    result.erase(result.begin() + j, result.begin() + j + 1);
                    result[matchFirst] = myResult3;
                    j--;
                }
                else
                {
                    matchFirst = j;
                    result[j] = myResult2;
                    match = true;
                }
    
            }
    
        }
    
        if(!match)
        {
            result.push_back(myList[i]);
        }
    }
    

    Edit: Fixed a bug.