繁体   English   中英

在C ++中找到数组的模式(最常见的元素)

[英]Find the mode (most common element) of an array in C++

我有一个面试问题。 我想看看StackOverflow如何做到的。

Bjarne Stroustrop将如何看待我呢? 有点罗word,但不幸的是,我不知道如何改善它。 我知道你们会笑我的愚蠢的。

template <class T>
T mode(T* arr, size_t n)
// If there's a tie, return an arbitrary element tied for 1st
// If the array size is 0, throw an error
{
   if (n == 0)
   {
       throw("Mode of array of size 0 is undefined, bro.");
   }
   else if (n == 1)
   {
       return arr[0];
   }
   else 
   {
      std::pair<T, int> highest(arr[0], 1);
      std::map<T, int> S;
      S.insert(highest);
      for (T* thisPtr(arr + 1), lastPtr(arr+n); thisPtr != lastPtr; ++thisPtr)
      {
          if (S.count(*thisPtr) == 0)
          {
             S.insert(std::pair<T, int> (*thisPtr, 1);
          }
          else 
          {
             ++S[*thisPtr];
             if (S[*thisPtr] > highest.second)
             {
                 highest = std::pair<T, int> (*thisPtr, S[*thisPtr]);
             }
          }
      }
   }
}

只要T实现std::hash ,您就可以这样做:

std::unordered_multiset<T> elems;
std::for_each(arr, arr + size, [&elems](T const & elem) { elems.insert(elem); }

//Now you have elems.count() for each entry
auto max_count = /*Guaranteed minimum value*/
T mode{};
for (auto const & set_elem : elems) {
    if (max(elems.count(set_elem), max_count) == max_count)) {
      mode = set_elem;
    }
}

我想我会使用std::map进行计数,然后找到计数最大的项目:

template <class T>
T mode(T* arr, size_t n) {
    std::map<T, size_t> counts;

    for (size_t i=0; i<n; i++)
        ++counts[arr[i]];

    return max_element(counts.begin(), counts.end(), 
        [](std::pair<T, size_t> const &a, std::pair<T, size_t> const &b) {
            return a.second < b.second;
        })->first;
}

如果期望大量独特项,则可能需要使用std::unordered_map而不是std::map [应将预期的复杂度从O(n log n)降低为O(N)]。

我发现您的代码存在以下问题。

冗余校验n == 1

您可以删除块

else if (n == 1)
{
    return arr[0];
}

而不会影响结果。

在for循环中声明变量:

T* thisPtr(arr + 1), lastPtr(arr+n);`

相当于

T* thisPtr(arr + 10); T lastPtr(arr+n);

那不是你的意图。 编译器也会报告错误。 因此,将其声明移到for循环之外。 更改

for (T* thisPtr(arr + 1), lastPtr(arr+n); thisPtr != lastPtr; ++thisPtr)

T* thisPtr(arr + 1);
T* lastPtr(arr+n);
for ( ; thisPtr != lastPtr; ++thisPtr)

简化for循环的内容

线

if (S.count(*thisPtr) == 0)
{
   S.insert(std::pair<T, int> (*thisPtr, 1));
}

可以替换为

 ++S[*thisPtr];

这正是您在接下来的else块中所做的。

您可以将整个for循环的内容更改为:

++S[*thisPtr];
if (S[*thisPtr] > highest.second)
{
   highest = std::pair<T, int> (*thisPtr, S[*thisPtr]);
}

您需要返回模式

  return highest.first;

else块关闭之前。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM