C++查找在向量向量中的所有子向量中都出现的第一个项目?

huangapple go评论78阅读模式
英文:

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

问题

给定一个包含 n 个向量的向量,其中 n 是未知的或可以变化的,如何找到在所有子向量中都出现的第一个项?<br>
例如,在这种情况下:

std::vector&lt;std::vector&lt;int&gt;&gt; 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 } };

答案将是 12(对于每个子向量从左到右,12 是出现在所有子向量中的第一个数字)。

我知道在这种情况下,因为只有 4 个子向量,我可以硬编码一个 4 层循环来实现这一点,但我需要一个能够适应未知或可变数量的内部向量的解决方案。

-- 编辑 1 --

对于@harold的评论添加澄清

子向量不总是按顺序排列,我只是在这个示例中这样做,以便更容易查看。

如果有两个数字出现的时间一样快,那么任何一个数字都是可以接受的。例如:

std::vector&lt;std::vector&lt;int&gt;&gt; vec = { { 0, 1 },
                                      { 1, 0 } };

那么 01 都是可以接受的。

-- 编辑 2 --

对于@PaulMcKenzie的评论添加澄清

如果没有在所有子向量中都相同的项,那么最好返回某种错误代码,例如 -9999。我唯一能想到的其他可能性是引发一个错误,然后调用者必须检查并知道如何处理。

-- 编辑 3 --

对于@PaulMcKenzie的评论进一步澄清

每个子向量中的数字可能不是唯一的。例如:

std::vector&lt;std::vector&lt;int&gt;&gt; vec = { { 1, 2, 3, 1 },
                                      { 2, 3, 4, 3 },
                                      { 1, 2, 1, 3 } };

所有 3 个子向量都有重复项。23 是所有子向量中都出现的唯一值。考虑值 23,其中一个最早出现在第二个子向量中的索引 0,所以答案是 2

英文:

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?<br>
For example in this case:

std::vector&lt;std::vector&lt;int&gt;&gt; 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&lt;std::vector&lt;int&gt;&gt; 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&lt;std::vector&lt;int&gt;&gt; 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.

答案1

得分: 3

你可以使用std::unordered_mapstd::unordered_set来记录每个整数的计数,并返回达到子向量数量的第一个整数。

以下是示例:

#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <iostream>

size_t FirstNumberInAll(const std::vector<std::vector<int>>& vect)
{
    // 目标数量(子向量数量)
    size_t goal = vect.size();

    std::unordered_map<int, size_t> mapResults;
    std::unordered_set<int> setInt;

    for (auto& v : vect)
    {
        // 在每个子向量处理的开始清空set
        setInt.clear();

        for (auto& v2 : v)
        {
            // 如果数字不在set中
            // 将其添加到set中,更新计数,并
            // 检查是否达到目标数量
            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);
}

输出:

12
英文:

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 &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;unordered_set&gt;
#include &lt;iostream&gt;

size_t FirstNumberInAll(const std::vector&lt;std::vector&lt;int&gt;&gt;&amp; vect)
{
    // The goal amount (number of sub vectors)
    size_t goal = vect.size();

    std::unordered_map&lt;int, size_t&gt; mapResults;
    std::unordered_set&lt;int&gt; setInt;

    for (auto&amp; v : vect)
    {
        // Clear this at the start of each subvector processing
        setInt.clear();

        for (auto&amp; 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&lt;std::vector&lt;int&gt;&gt; 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 &lt;&lt; FirstNumberInAll(vec);
}

Output:

12

答案2

得分: 1

一个简单的方法是:

构建第一个数组的集合。
构建第二个数组的集合。
构建一个是第一个两个集合交集的集合。
继续将此集合与从其他列表构建的集合进行交集运算。
以您认为应首先考虑的项目升序顺序迭代向量。
在最终交集集合中首次遇到的项目是结果。

这个算法的复杂度很容易计算,我认为很难轻易改进。

英文:

An easy approach would be:

Construct a set of the first array.
Construct a set of the second array.
Construct a set which is an intersection of the first two sets.
Continue intersecting this set with sets constructed from the rest of the lists.
Iterate the vectors in an order which you consider ascending in respect to which item should be considered first.
The first encountered item which is present in the final intersected set is the result.

The complexity of this algorithm is easy to calculate and I think it cannot be easily improved.

答案3

得分: 1

这是我的相对简单的解决方案:

#include <iostream>
#include <vector>

// 函数原型
int findFirstNumInAll(const std::vector<std::vector<int>>& vec);

int main()
{
    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 } };

    int firstNumInAll = findFirstNumInAll(vec);

    std::cout << "\n" << "firstNumInAll = " << firstNumInAll << "\n\n";

    return 0;
}

int findFirstNumInAll(const std::vector<std::vector<int>>& vec)
{      
    std::vector<int> mergedVec = vec[0];
    std::vector<int> newMergedVec;
    for (unsigned int i = 1; i < vec.size(); i++)
    {
        // 创建一个包含来自mergedVec和vec[i]的匹配值的向量
        for (unsigned int j = 0; j < mergedVec.size(); j++)
        {
            for (unsigned int k = 0; k < vec[i].size(); k++)
            {
                if (mergedVec[j] == vec[i][k]) newMergedVec.push_back(mergedVec[j]);
            }
        }

        mergedVec = newMergedVec;
        newMergedVec.clear();
    }

    return mergedVec[0]; 
}

我认为@PaulMcKenzie的解决方案更快,所以我会将其标记为答案。

英文:

Here is my relatively simple solution:

#include &lt;iostream&gt;
#include &lt;vector&gt;

// function prototypes
int findFirstNumInAll(const std::vector&lt;std::vector&lt;int&gt;&gt;&amp; vec);


int main()
{
std::vector&lt;std::vector&lt;int&gt;&gt; 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 } };
  
  int firstNumInAll = findFirstNumInAll(vec);
  
  std::cout &lt;&lt; &quot;\n&quot; &lt;&lt; &quot;firstNumInAll = &quot; &lt;&lt; firstNumInAll &lt;&lt; &quot;\n\n&quot;;
  
  return 0;
}

int findFirstNumInAll(const std::vector&lt;std::vector&lt;int&gt;&gt;&amp; vec)
{      
  std::vector&lt;int&gt; mergedVec = vec[0];
  std::vector&lt;int&gt; newMergedVec;
  for (unsigned int i = 1; i &lt; vec.size(); i++)
  {
    // make a vector with the matching values from mergedVec and vec[i]
    for (unsigned int j = 0; j &lt; mergedVec.size(); j++)
    {
      for (unsigned int k = 0; k &lt; vec[i].size(); k++)
      {
        if (mergedVec[j] == vec[i][k]) newMergedVec.push_back(mergedVec[j]);
      }
    }
    
    mergedVec = newMergedVec;
    newMergedVec.clear();
  }
  
  return mergedVec[0]; 
}

I think @PaulMcKenzie's solution above is much faster though, so I'll mark that as the answer.

huangapple
  • 本文由 发表于 2023年6月19日 08:33:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76503020.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定