Search code examples
c++vector

C++ find first item that occurs in all sub-vectors in a vector of vectors?


Given a vector containing n number of vectors, where n is unknown or can change, how can I find the first item that occurs in all the sub-vectors?
For example in this case:

std::vector<std::vector<int>> vec = { { 5,  7, 11, 12, 17, 23, 27 },
                                      { 8, 10, 12, 15, 17, 23, 28 },
                                      { 1,  2,  5,  6, 12, 22, 23 },
                                      { 3,  7,  9, 12, 17, 23, 28 } };

the answer would be 12 (going from left to right for each of the 4 sub-vectors, 12 is the first number that appears in all sub-vectors).

I'm aware that in this case since there are only 4 sub-vectors I could hard-code a 4 layer loop to achieve this, but I need a solution that would work with the number of inner vectors not being known or changing.

-- Edit 1 --

Adding clarification for comment by @harold

The sub-vectors will not always be sorted, I just made it that way in this example so it's easier to look at.

If 2 numbers occur equally soon, then either number would be acceptable. For example given:

std::vector<std::vector<int>> vec = { { 0, 1 },
                                      { 1, 0 } };

Then either 0 or 1 would be acceptable.

-- Edit 2 --

Adding clarification for comment by @PaulMcKenzie

If there is not identical item that is in all the sub-vectors, then it would be preferable to return some sort of error code, ex. -9999. The only other possibility I could figure would be to cause an error to happen that the caller would then have to check for and know to handle.

-- Edit 3 --

Adding further clarification for comment by @PaulMcKenzie

The numbers within each sub-vector may not be unique. For example:

std::vector<std::vector<int>> vec = { { 1, 2, 3, 1 },
                                      { 2, 3, 4, 3 },
                                      { 1, 2, 1, 3 } };

All 3 sub-vectors have duplicates. 2 and 3 are the only values that appear in all sub-vectors. Considering values 2 and 3, the earliest appearance of either is for value 2 index 0 in the 2nd sub-vector, so 2 would be the answer.


Solution

  • You could use an std::unordered_map along with a std::unordered_set to keep a count of the each integer, and return the first integer that reaches the number of sub-vectors.

    Here is an example:

    #include <vector>
    #include <unordered_map>
    #include <unordered_set>
    #include <iostream>
    
    size_t FirstNumberInAll(const std::vector<std::vector<int>>& vect)
    {
        // The goal amount (number of sub vectors)
        size_t goal = vect.size();
    
        std::unordered_map<int, size_t> mapResults;
        std::unordered_set<int> setInt;
    
        for (auto& v : vect)
        {
            // Clear this at the start of each subvector processing
            setInt.clear();
    
            for (auto& v2 : v)
            {
                // If number is not already in the set
                // add it to the set, update the count and
                // check if the goal amount has been reached
                if ( !setInt.count(v2) )
                {
                    ++mapResults[v2];
                    if (mapResults[v2] == goal)
                        return v2;
                    setInt.insert(v2);
                }
            }
        }
        return -9999;
    }
    
    int main()
    {
        std::vector<std::vector<int>> vec = { { 5,  7, 11, 12, 12, 12, 17, 23, 27 },
                                              { 8, 10, 12, 15, 17, 23, 28 },
                                              { 1,  2,  5,  6, 12, 22, 23 },
                                              { 3,  7,  9, 12, 17, 23, 28 } };
        std::cout << FirstNumberInAll(vec);
    }
    

    Output:

    12