【问题标题】:Find which numbers appears most in a vector找出向量中出现次数最多的数字
【发布时间】:2010-03-21 22:08:30
【问题描述】:

我有一些数字存储在std::vector<int> 中。我想找出向量中出现最多的数字。

例如在向量中

1 3 4 3 4 2 1 3 2 3

出现次数最多的元素是3

是否有任何算法(STL 或其他)可以做到这一点?

【问题讨论】:

标签: c++ vector


【解决方案1】:

对它进行排序,然后遍历它并保留一个计数器,当当前数字与前一个数字相同时递增,否则重置为 0。还要跟踪到目前为止计数器的最高值是多少,以及达到该值时的当前数字是多少。这个解决方案是O(n log n)(因为排序)。

或者,您可以使用从 int 到 int 的 hashmap(或者如果您知道数字在有限范围内,您可以只使用数组)并遍历向量,将 the_hashmap[current_number] 每个数字增加 1。然后遍历 hashmap 以找到它的最大值(以及属于它的键)。这需要一个 hashmap 数据结构(除非您可以使用更快的数组),这不是 STL 的一部分。

【讨论】:

  • 只是补充一点,使用 STL 的排序进行排序:cplusplus.com/reference/algorithm/sort
  • @Steve314:unordered_map 将在即将发布的标准中。它不在 2003 年(即当前)标准中。
  • 奇怪 - 我不知何故知道 TR1 是 2003 年的“第一次文本修订”。
  • @Steve314: ISO 14882:2003 实际上是 14882:1998 加上 TC1,TR1 只是一个“报告”而不是更正,还没有成为新版本的标准。
  • 您不需要两次通过。您可以一次完成此操作,“随时”跟踪最大计数。请参阅下面的代码。
【解决方案2】:

如果您想避免对矢量v 进行排序,请使用地图:

int max = 0;
int most_common = -1;
map<int,int> m;
for (vi = v.begin(); vi != v.end(); vi++) {
  m[*vi]++;
  if (m[*vi] > max) {
    max = m[*vi]; 
    most_common = *vi;
  }
}

这需要更多内存并且具有非常相似的预期运行时间。所需的内存应该在一个完整的向量副本的数量级上,如果有很多重复条目则更少。

【讨论】:

    【解决方案3】:

    试试这个

    int FindMode(vector<int> value)
    { 
        int index = 0;
        int highest = 0;
        for (unsigned int a = 0; a < value.size(); a++)
        {
            int count = 1;
            int Position = value.at(a);
            for (unsigned int b = a + 1; b < value.size(); b++)
            {
                if (value.at(b) == Position)
                {
                    count++;
                }
            }
            if (count >= index)
            {
                index = count;
                highest = Position;
            }
        }
        return highest;
    }
    

    【讨论】:

    • 虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请编辑您的答案以添加解释并说明适用的限制和假设。
    • 时间复杂度增加到 O(n^2) 有时太多了
    【解决方案4】:

    这就是我的做法:

        int max=0,mostvalue=a[0];
        for(i=0;i<a.size();i++)
        {
            co = (int)count(a.begin(), a.end(), a[i]);
            if(co > max)
            {       max = co;
                    mostvalue = a[i];
            }
        }
    

    我只是不知道它有多快,即 O() ?如果有人可以计算出来并把它贴在这里就好了。

    【讨论】:

    • 它是 O(n * n),所以不是最有效的方法,但它是只读的,如果重要的话,不需要额外的存储空间。
    • 这是 O(n^2),因为每次调用 count 时,它都会查看向量中的每个元素。可以在 O(n) (stackoverflow.com/questions/512590/…) 内完成
    【解决方案5】:

    这是一个 O(n) 的通用解决方案,用于在迭代器范围内查找最常见的元素。您只需执行以下操作即可使用它:

    int commonest = most_common(my_vector.begin(), my_vector.end());
    

    使用iterator_traits&lt;&gt;从迭代器中提取值类型。

    template<class InputIt, class T = typename std::iterator_traits<InputIt>::value_type>
    T most_common(InputIt begin, InputIt end)
    {
        std::map<T, int> counts;
        for (InputIt it = begin; it != end; ++it) {
            if (counts.find(*it) != counts.end()) {
                ++counts[*it];
            }
            else {
                counts[*it] = 1;
            }
        }
        return std::max_element(counts.begin(), counts.end(),
                [] (const std::pair<T, int>& pair1, const std::pair<T, int>& pair2) {
                return pair1.second < pair2.second;})->first;
    }
    

    【讨论】:

    • 这是 O(nlogn) 而不是 O(n) -- std::map 访问是 O(logn)。可以通过删除if来简化它,但它仍然是O(nlogn)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    相关资源
    最近更新 更多