在数组中查找模式的最有效方法是什么?

时间:2018-03-05 09:32:58

标签: c++ c arrays mode

最近我试图通过使用C找到一组数字中的模式。 当集合很小时,我的代码可以很好地完成。

这是我的代码:

int frequency[10001]; //This array stores the frequency of a number that between 0 to 10000
int main()
{
    int x[10]={1,6,5,99,1,12,50,50,244,50};
    int highest = 0;
    int i,j,k;

    for(i=0;i<10;i++)
    {
        frequency[x[i]]++;
        if(frequency[x[i]]>highest)
            highest = frequency[x[i]];
    }

    printf("The mode in the array : ");
    for(i=0;i<=10001;i++)
        if(frequency[i]==highest)
            printf("%d ",i);
    return 0;
}

后来,我发现如果有一大堆数字,我的方法会非常慢。此外,如果数字小于0或大于10000,我的程序将无法工作,除非我增加&#34;频率&#34;阵列。

因此,我想知道有没有办法可以更有效地找到阵列中的模式?感谢。

4 个答案:

答案 0 :(得分:1)

使用hash table。 (即unordered_map通常是这样实现的。)

您将问题标记为C ++,因此您将在C ++中获取一些示例代码。您可以自己在C中实现哈希表。这不是一个糟糕的学习练习。

int x[10]={1,6,5,99,1,12,50,50,244,50};
std::unordered_map<int, int> table; // map of items in "x" to the number of times observed.
for (int i = 0; i < 10; i++)
{
     table[x[i]]++;
}

int mode = 0;
int mode_freq = 0;
for (auto itor = table.begin(); itor != table.end(); itor++)
{
    if (itor->second > mode_freq)
    {
        mode = itor->first;
        mode_freq = itor->second;
    }
}
std::cout << "The mode in the array is " << mode << std::endl;

答案 1 :(得分:1)

您可以简单地对数组进行排序(man qsort),然后搜索相同数字的最长序列。 问题是:当两个数字同样出现在数组中的最频率时,你如何表现?

答案 2 :(得分:0)

我认为你的问题太笼统,无法得到明确答案:

  • “最有效”是一个非常大的要求,我想你会对任何“更有效”的解决方案感兴趣:)。
  • 以什么方式更有效率?执行时间更快?减少内存使用量?更好的代码?

首先,我会写这样的小作品:

static const size_t NUM_FREQ=1000;

int main()
{
    vector< unsigned int > frequency(NUM_FREQ);
    vector< unsigned int > samples[10]={1,6,5,99,1,12,50,50,244,50};
    int highest = 0;
    int i,j,k;

    for ( size_t i = 0; i < samples.size(); i++ )
    {
    assert( samples[i] < NUM_FREQ && "value in samples is bigger than expected" ); 
        frequency[ samples[ i ] ]++;
        if( frequency[ samples[ i ] ] > highest )
            highest = frequency[ samples[ i ] ];
    }

    printf("The mode in the array : ");
    for ( size_t i = 0; i < frequency.size(); i++ )
        if ( frequency[ i ] == highest )
            printf("%d ",i);
    return EXIT_SUCCESS;
}

在我改变的所有不良做法中,你应该更加小心的是依赖普通类型隐式初始化。

现在,有很多事情可能会或可能没有错:

  • 最明显的是你不需要循环两次,只需使用一个额外的变量来记住最高频率的位置并彻底摆脱第二个循环。

  • 在您的示例中,样本非常少,使用如此大的频率阵列会浪费空间。如果样本的大小小于NUM_FREQ,我只需使用对向量。我假设你的真实应用程序使用的是比频率数组更大的样本数组。

  • 最后排序或散列可以加快速度,但这在很大程度上取决于频率数据在其他应用程序中的使用方式(但除了这个简单的代码之外,你没有显示任何内容)。

    < / LI>

答案 3 :(得分:0)

  • 您找不到否定号码。您只能找到号码的出现次数。
  • 而不是使用frequency[10001]数组使用MAPS in C++

现在让我修改你的代码。用map而不是数组。

#include <bits/stdc++.h>
using namespace std;
int main()
{
  int x[10]={1,6,5,99,1,12,50,50,244,50};
  map <int, int> freq;//using map here instead of frequency array
  int highiest=0;
  for(int i=0;i<10;i++)
  {
    freq[x[i]]+=1;//indexing
  }
  for(int i=0;i<sizeof(freq);i++)
  {
    if(freq[i]>highiest)//finding the highiest occurancy of a number.
    highiest=i;
  }
  cout<<highiest<<endl;//printing the highiest occurancy number
}