[英]Find the mode (most common element) of an array in C++
I had this on an interview question. 我有一个面试问题。 I'd like to see how StackOverflow would do it. 我想看看StackOverflow如何做到的。
What would Bjarne Stroustrop think of my way? Bjarne Stroustrop将如何看待我呢? It's a little wordy, but I don't know how to make it better, unfortunately. 有点罗word,但不幸的是,我不知道如何改善它。 I know you guys are gonna laugh at my stupidity. 我知道你们会笑我的愚蠢的。
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]);
}
}
}
}
}
You could do this, provided that T implements std::hash
: 只要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;
}
}
I think I'd use an std::map
to do the counting, then find the item with the largest count: 我想我会使用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;
}
If you expect a really large number of unique items, you might want to use an std::unordered_map
instead of a std::map
[should reduce expected complexity from O(n log n) to O(N)]. 如果期望大量独特项,则可能需要使用std::unordered_map
而不是std::map
[应将预期的复杂度从O(n log n)降低为O(N)]。
I found the following issues with your code. 我发现您的代码存在以下问题。
Redundant check n == 1
冗余校验n == 1
You can remove the block 您可以删除块
else if (n == 1)
{
return arr[0];
}
without affecting the outcome. 而不会影响结果。
Declaration of the variables in the for loop: 在for循环中声明变量:
T* thisPtr(arr + 1), lastPtr(arr+n);`
is equivalent to 相当于
T* thisPtr(arr + 10); T lastPtr(arr+n);
That's not what your intention is. 那不是你的意图。 The compiler will report an error too. 编译器也会报告错误。 So, move their declaration outside the for
loop. 因此,将其声明移到for
循环之外。 Change 更改
for (T* thisPtr(arr + 1), lastPtr(arr+n); thisPtr != lastPtr; ++thisPtr)
to 至
T* thisPtr(arr + 1);
T* lastPtr(arr+n);
for ( ; thisPtr != lastPtr; ++thisPtr)
Simplify the contents of the for
loop 简化for
循环的内容
The lines 线
if (S.count(*thisPtr) == 0)
{
S.insert(std::pair<T, int> (*thisPtr, 1));
}
can be replaced by 可以替换为
++S[*thisPtr];
which is exactly what you are doing in the following else
block. 这正是您在接下来的else
块中所做的。
You can change the contents of the entire for
loop to: 您可以将整个for
循环的内容更改为:
++S[*thisPtr];
if (S[*thisPtr] > highest.second)
{
highest = std::pair<T, int> (*thisPtr, S[*thisPtr]);
}
You need to return the mode 您需要返回模式
Add 加
return highest.first;
before the closing of the else
block. 在else
块关闭之前。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.