C++找到所有子向量中出现的第一个元素?

zfycwa2u  于 2023-06-25  发布在  其他
关注(0)|答案(3)|浏览(157)

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

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

答案将是12(对于4个子向量中的每一个从左到右,12是出现在所有子向量中的第一个数字)。
我知道,在这种情况下,因为只有4个子向量,我可以硬编码一个4层循环来实现这一点,但我需要一个解决方案,将与内部向量的数量未知或变化。

--编辑1 --

添加@harold的评论说明
子向量并不总是排序的,我只是在这个例子中这样做,所以它更容易看。
如果两个数字同样快出现,那么任何一个数字都可以接受。例如:

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

那么01都是可以接受的。

--编辑2 --

添加@PaulMcKenzie的评论澄清
如果在所有子向量中不存在相同的项,则优选地返回某种错误代码,例如。-9999。我能想到的唯一其他可能性是导致错误发生,然后调用者必须检查并知道如何处理。

--编辑3 --

@PaulMcKenzie添加进一步澄清以供评论
每个子向量内的数字可以不是唯一的。例如:

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

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

5q4ezhmt

5q4ezhmt1#

您可以使用std::unordered_map沿着std::unordered_set来记录每个整数的计数,并返回达到子向量数量的第一个整数。
下面是一个例子:

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

输出:

  1. 12
展开查看全部
b5lpy0ml

b5lpy0ml2#

一个简单的方法是:
构造一组第一个数组。
构造一组第二个数组。
构造一个集合,它是前两个集合的交集。
继续将该集合与从列表的其余部分构造的集合相交。
按照您认为应该首先考虑的项的升序顺序迭代向量。
出现在最终相交集中的第一个遇到的项是结果。
这个算法的复杂度很容易计算,我认为它不容易改进。

eufgjt7s

eufgjt7s3#

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

  1. #include <iostream>
  2. #include <vector>
  3. // function prototypes
  4. int findFirstNumInAll(const std::vector<std::vector<int>>& vec);
  5. int main()
  6. {
  7. std::vector<std::vector<int>> vec = { { 5, 7, 11, 12, 17, 23, 27 },
  8. { 8, 10, 12, 15, 17, 23, 28 },
  9. { 1, 2, 5, 6, 12, 22, 23 },
  10. { 3, 7, 9, 12, 17, 23, 28 } };
  11. int firstNumInAll = findFirstNumInAll(vec);
  12. std::cout << "\n" << "firstNumInAll = " << firstNumInAll << "\n\n";
  13. return 0;
  14. }
  15. int findFirstNumInAll(const std::vector<std::vector<int>>& vec)
  16. {
  17. std::vector<int> mergedVec = vec[0];
  18. std::vector<int> newMergedVec;
  19. for (unsigned int i = 1; i < vec.size(); i++)
  20. {
  21. // make a vector with the matching values from mergedVec and vec[i]
  22. for (unsigned int j = 0; j < mergedVec.size(); j++)
  23. {
  24. for (unsigned int k = 0; k < vec[i].size(); k++)
  25. {
  26. if (mergedVec[j] == vec[i][k]) newMergedVec.push_back(mergedVec[j]);
  27. }
  28. }
  29. mergedVec = newMergedVec;
  30. newMergedVec.clear();
  31. }
  32. return mergedVec[0];
  33. }

我认为@PaulMcKenzie上面的解决方案要快得多,所以我将其标记为答案。

展开查看全部

相关问题