找到最常输入C的数字的最佳(最快)方式?

时间:2013-12-02 06:45:07

标签: c optimization

嗯,我认为这个标题基本上解释了我的怀疑。我将 n 数字读取,此 n 数字从 1 变为 x ,其中x最多10 5 。什么是最快(运行它的可能时间更短)找出更多次插入的数字的方法? 知道大多数时间出现的次数超过一半

到目前为止我尝试过:

//for (1<=x<=10⁵)
int v[100000+1];

//multiple instances , ends when n = 0
while (scanf("%d", &n)&&n>0) {
    zerofill(v);
    for (i=0; i<n; i++) {
        scanf("%d", &x);
        v[x]++;
        if (v[x]>n/2)
            i=n;
    }
    printf("%d\n", x);
}

x 位置数组进行零填充并增加位置向量[x],同时验证向量[x]是否大于n / 2,足够快。

任何想法都可能有所帮助,谢谢。

观察:无需关心使用的内存量。

2 个答案:

答案 0 :(得分:6)

保持计数器阵列的简单解决方案是O(n),你显然不可能比这更好。然后是关于常数的争论,这是很多细节将在游戏中发挥作用的地方,包括nx的确切价值,什么样的处理器,什么样的架构等等上。

另一方面,这似乎真的是“淘汰”问题,但该算法将需要两次传递数据和一个额外的条件,因此在计算机实际上我知道它将最有可能比数组慢计算许多nx值的解决方案。

淘汰赛解决方案的优点是您不需要对值设置限制x,也不需要任何额外的内存。

如果您已经知道存在绝对多数的值(并且您只需要找到该值是什么)那么这可以实现(但内部循环中有两个条件):

  • 初始化count = 0
  • 遍历所有元素
  • 如果count0,则设置champion = elementcount = 1
  • 如果element != champion递减count
  • ,则为其他人
  • 其他增加count

在循环结束时,champion将是绝对多数元素的值,如果存在这样的值。

但正如之前所说,我期待一个微不足道的

for (int i=0,n=size; i<n; i++) {
    if (++count[x[i]] > half) return x[i];
}

更快。

修改

在您的编辑之后,您似乎真的在寻找淘汰赛算法,但关注速度可能仍然是现代计算机的错误问题(今天,100000个元素对于指甲大小的单个芯片来说也没什么用。)

答案 1 :(得分:1)

我认为你可以为你读取的数量创建一个最大堆,并使用堆排序来查找大于n / 2的所有计数