在数组中找到大多数出现元素

时间:2010-09-26 14:40:46

标签: c++

这是一个简单的程序,用于查找最常出现在数组中的元素:

#include <cstdlib>
#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char *argv[]) {
    int a[] = {1,2,3,4,4,4,5};
    int n = sizeof(a) / sizeof(int);
    int max = 0;
    int result = 0;
    int *b = new int[n];
    for (int i = 0;  i < n;  i++) {
        b[a[i]] = (b[a[i]] || 0) + 1;
        if (b[a[i]] > max) {
            max = b[a[i]];
            result = a[i];
        }
    }
    cout << result << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}

但它不起作用;它打印1。为什么呢?

5 个答案:

答案 0 :(得分:11)

由于您要包含矢量,为什么不将int *b=new int [n];替换为std::vector<int> b(n)?这也需要释放内存,你忘了delete[] b

但正如其他人所提到的,如果数组包含大于n的元素,则解决方案将会中断。更好的方法可能是使用映射到int来计算元素。这样,您还可以计算不能用作数组索引的元素,例如字符串。

也没有理由将自己局限于数组。这是一个通用解决方案,适用于任何低于可比元素类型的容器:

#include <algorithm>
#include <iterator>
#include <map>

struct by_second
{
    template <typename Pair>
    bool operator()(const Pair& a, const Pair& b)
    {
        return a.second < b.second;
    }
};


template <typename Fwd>
typename std::map<typename std::iterator_traits<Fwd>::value_type, int>::value_type
most_frequent_element(Fwd begin, Fwd end)
{
    std::map<typename std::iterator_traits<Fwd>::value_type, int> count;

    for (Fwd it = begin; it != end; ++it)
        ++count[*it];

    return *std::max_element(count.begin(), count.end(), by_second());
}

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> test {1, 2, 3, 4, 4, 4, 5};
    std::pair<int, int> x = most_frequent_element(test.begin(), test.end());
    std::cout << x.first << " occured " << x.second << " times";
}

答案 1 :(得分:6)

您尚未初始化数组b。你可以这样做:

int *b=new int [n]();
                  ^^

完成后,您可以将频率数组递增为:

b[a[i]]++;

取代

b[a[i]]=(b[a[i]]||0)+1;

您执行(b[a[i]]||0)+1的方式适用于Javascript,Perl等语言,其中未初始化的数组元素将具有名为undefnull的特殊值。 C ++没有这样的东西,未初始化的数组将有垃圾

答案 2 :(得分:1)

您需要将数组b初始化为零。

 b[a[i]]||0

不起作用,你不知道b中最初是什么。

更短的代码:

int main(int argc, char *argv[])
{
    int a[]={1,2,3,4,4,4,5};
    int n = sizeof(a)/sizeof(int );
    int *b=new int [n];
    fill_n(b,n,0); // Put n times 0 in b

    int val=0; // Value that is the most frequent
    for (int i=0;i<n;i++)
        if( ++b[a[i]] >= b[val])
            val = a[i];

    cout<<val<<endl;
    delete[] b;
    return 0;
}

注意: 如果最大值低于数组a中的值数,那么你的代码(我的代码)也只能工作。

如果不是这种情况并且最大值远远大于元素数量,则可能需要对数组进行排序,然后在线性时间(和常量空间)中搜索最大值。

答案 3 :(得分:0)

这里,O(n)及时,O(1)在空间通用解决方案中工作于有序范围。

#include <iostream>

template <class ForwardIterator>
ForwardIterator
most_common(ForwardIterator first, ForwardIterator last) {
  /** Find the most common element in the [first, last) range.

      O(n) in time; O(1) in space.

      [first, last) must be valid sorted range.
      Elements must be equality comparable.
  */
  ForwardIterator it(first), max_it(first);
  size_t count = 0, max_count = 0;
  for ( ; first != last; ++first) {
    if (*it == *first) 
      count++;
    else {
      it = first;
      count = 1;
    }      
    if (count > max_count) {
      max_count = count;
      max_it = it;
    }
  }  
  return max_it;
}    
int main() {
  int a[] = {1, 2, 3, 4, 4, 4, 5};
  const size_t len = sizeof(a) / sizeof(*a);
  std::cout << *most_common(a, a + len) << std::endl;
}

答案 4 :(得分:0)

利用事实地图的实现已经过排序。

#include <iostream>
#include <vector>
#include <map>

using namespace std;

template<class T> pair<T, int> getSecondMostOccurance(vector<T> & v) {
    map<T, int> m;

    for ( int i = 0; i < v.size(); ++i ) {
        m[ v[i] ]++;
    }
    return *m.end();
}

int main() {
    int arr[] = {1, 4, 5, 4, 5, 4};
    pair<int, int> p = getSecondMostOccurance(vector<int>(arr, arr+7));
    cout << "element: " << p.first << " count: " << p.second << endl;
    return 0;
}