嗯,我认为这个标题基本上解释了我的怀疑。我将 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,不强大>足够快。
任何想法都可能有所帮助,谢谢。
观察:无需关心使用的内存量。
答案 0 :(得分:6)
保持计数器阵列的简单解决方案是O(n)
,你显然不可能比这更好。然后是关于常数的争论,这是很多细节将在游戏中发挥作用的地方,包括n
和x
的确切价值,什么样的处理器,什么样的架构等等上。
另一方面,这似乎真的是“淘汰”问题,但该算法将需要两次传递数据和一个额外的条件,因此在计算机实际上我知道它将最有可能比数组慢计算许多n
和x
值的解决方案。
淘汰赛解决方案的优点是您不需要对值设置限制x
,也不需要任何额外的内存。
如果您已经知道存在绝对多数的值(并且您只需要找到该值是什么)那么这可以实现(但内部循环中有两个条件):
count = 0
count
为0
,则设置champion = element
和count = 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的所有计数