【问题标题】:How to check whether a vector is a subset of another in c++如何在c ++中检查一个向量是否是另一个向量的子集
【发布时间】:2011-08-02 01:54:31
【问题描述】:

我试图找到一种简单的方法来检查一个向量是否是另一个向量的子集,而无需对向量中元素的顺序进行排序。两个向量都包含随机数元素。

std::includes 似乎只适用于排序范围。我怎样才能做到这一点?

【问题讨论】:

  • 如果向量 #1 有重复项怎么办?向量 #2 是否也必须有相似的重复项?
  • 为什么需要这样做?对它们进行排序有什么不好?
  • 听起来你应该首先选择std::set,可能。你确定std::vector是你想要的吗?
  • 相关:stackoverflow.com/questions/4068141/…(尽管唯一有用的答案是关于 std::includes,您是正确的:它假定输入已排序)。
  • 两个向量都没有重复项

标签: c++ vector


【解决方案1】:

复制向量。对副本进行排序。然后在副本上使用std::includes

template <typename T>
bool IsSubset(std::vector<T> A, std::vector<T> B)
{
    std::sort(A.begin(), A.end());
    std::sort(B.begin(), B.end());
    return std::includes(A.begin(), A.end(), B.begin(), B.end());
}

【讨论】:

  • “我正在尝试找到一种简单的方法来检查一个向量是否是另一个向量的子集,而无需对向量中元素的顺序进行排序。”如果排序是答案,那么您的问题非常非常糟糕。
  • @Benjamin:同意,这没有理由被否决。这是所有给出的答案中最聪明的方法。如果 OP 真的想在不修改数据的情况下检查两件事是否是彼此的子集,那么这就是要走的路。这实际上可能总共大约 5 行代码。如果确切的要求是“我需要检查一个是否是另一个的子集,使用O(1) 内存并且不替换任一向量的数据”,答案将是以下两个之一。
  • @Benjamin:因为您没有像 Tomalak 所说的那样回答“查找...而不排序...”的问题。
  • @arasmussen:似乎“无排序”要求是 OP 从未完全解决的潜在问题的症状。他描述了他想做的事情,但没有描述他真正想要完成的事情。我看到过一些问题(我一直因为问这样的问题而感到内疚),其中发布者要求一件事,认为这是解决方案,但有一个更简单的解决方案,不需要奇怪的要求。
  • @arasmussen:问题不是“查找...没有排序...”。如果是这样,我会投票结束这个问题,因为这是一个不适用于现实生活编程的任意要求。要求是 OP 不希望对他的 own 向量进行排序。那一个可能适用于现实生活编程的要求,所以我回答了那个问题。
【解决方案2】:

我的回答假设当您说“子集”时,您实际上是在寻找更多与“子字符串”等效的内容;也就是说,在搜索过程中保持元素的顺序。


最终,我看不出你怎么能在O(n*m) 以外的地方做到这一点。鉴于此,您可以非常简单地自己滚动:

template <typename T1, typename T2>
bool contains(std::vector<T1> const& a, std::vector<T2> const& b) {
   for (typename std::vector<T1>::const_iterator i = a.begin(), y = a.end(); i != y; ++i) {
      bool match = true;

      typename std::vector<T1>::const_iterator ii = i;
      for (typename std::vector<T2>::const_iterator j = b.begin(), z = b.end(); j != z; ++j) {
          if (ii == a.end() || *j != *ii) {
              match = false;
              break;
          }
          ii++;
      }

      if (match)
         return true;
   }

   return false;
}

Live demo.

(您可能对模板参数更有创意。)

【讨论】:

  • 2011 年对于 C++ 来说是一个可怕的时期!
【解决方案3】:

这是假设重复并不重要。因此,如果向量 a 中有两个数字 99 的实例,那么只要向量 b 至少有一个数字 99 的实例,那么它将被声明为一个子集。

bool isSubset(const std::vector<int>& a, const std::vector<int>& b)
{
    for (std::vector<int>::const_iterator i = a.begin(); i != a.end(); i++)
    {
        bool found = false;

        for (std::vector<int>::const_iterator j = b.begin(); j != b.end(); j++)
        {
            if (*i == *j)
            {
                found = true;
                break;
            }
        }

        if (!found)
        {
            return false;
        }
    }

    return true;
}

【讨论】:

  • 所以建议的解决方案不是 n*log(n) 复杂度,而是 n^2 复杂度(而且它也是一个糟糕的 c++)
  • 为什么要另一种方法?你不想对它进行排序,你不想遍历它们中的每一个......还有一个更大的问题你没有告诉我们吗?
  • @Gene:谁在排序?这个问题是关于在 unsorted 范围内搜索的。
  • @Gene,比如?我问的是学生。
  • @arasmussen -- 不必要的副本,未初始化的变量,不必要的长生命周期,通常是 c 风格的代码
【解决方案4】:

没有排序...

template <typename T>
bool isSubsetOrEqual(std::vector<T> const& a, std::vector<T> const& b) {
   for(auto const& av:a){
      if(std::find(b.begin(),b.end(),av)==b.end())
          return false;
   }
   return true;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    相关资源
    最近更新 更多