Java中最有效的模式函数

Java中最有效的模式函数,java,mode,Java,Mode,我有一个巨大的整数数组,我需要找到它的模式 我见过一些方法使用2个循环(一个嵌套),这似乎是不必要的 我认为找到只有一个循环的模式的唯一方法是使用Maps: int[] elements = new int[]{....numbers...}; Map<Integer,Integer> map = new .....Map Type....; for(int number : elements){ if(map.containsKey(Integer.valueOf(numb

我有一个巨大的整数数组,我需要找到它的模式

我见过一些方法使用2个
循环(一个嵌套),这似乎是不必要的

我认为找到只有一个循环的模式的唯一方法是使用
Map
s:

int[] elements = new int[]{....numbers...};
Map<Integer,Integer> map = new .....Map Type....;
for(int number : elements){
    if(map.containsKey(Integer.valueOf(number))){
        map.put(Integer.valueOf(number),map.get(Integer.valueOf(number))+1);
    }else{
        map.put(Integer.valueOf(number),1);
    }
}
int[]元素=新的int[]{…数字…};
Map Map=新的…..地图类型。。。。;
for(整数:元素){
if(map.containsKey(Integer.valueOf(number))){
map.put(Integer.valueOf(number),map.get(Integer.valueOf(number))+1;
}否则{
map.put(整数.valueOf(number),1);
}
}
我不确定使用地图会带来什么样的速度优势。
有更好的方法吗?

如果使用哈希映射,算法的运行时复杂度应该是O(n):访问n个元素中的每个元素一次,哈希映射查找和写入通常假定为O(1)。总的来说,你得到O(n*1),也就是O(n)。如果使用树映射,则得到O(n logn)

与两个嵌套循环(听起来像O(n²))相比,速度从二次循环提高到线性循环,这是非常好的:对于1000个元素,执行1000个“步骤”,而不是1000000个


p.S.在这里,比线性更好可能很难——无法想象一种不访问每个元素至少一次的计算方法

正如Stefan Haustein所写,使用映射比使用2 for循环复杂得多

如果您知道数组中存储的数字范围,则可以进一步改进或专门化。例如,如果计算0-255范围内的颜色,则不必使用贴图,而可以使用简单数组

int[] elements = new int[]{....numbers...};
int[] histogram = new int[256]; // 255 = highest possible value in elements
for(int number : elements){
  ++histogram[number];    
}

使用地图是一种更普遍的方式。可以将贴图视为具有更复杂索引功能的数组。因此,在普通数组中,数字位于
数组指针+索引处,而在映射中,这是使用线性散列函数计算的。

没有算法比O(n)更快(请查看wikipedia页面了解更多信息)。至少,不一致(在所有可能的输入中)。这并不意味着它不能再快了——只是,超过一定的问题规模,任何更快的东西都不能继续将速度差增加超过一个(可能很小的)线性因子

这是因为,无论您检查元素的顺序如何,给定一个对胜利者“几乎平衡”的数组,您检查的最后一个元素可能会成为平局破坏者。给我任何一个算法,它不看所有的元素,我就可以编写一个输入数组,让它返回不正确的结果。因此,您必须至少检查一次它们:O(n)复杂性


HashMap的插入和查找复杂性一般为O(1)——也就是说,平均而言,不管数据大小如何,它们都会占用固定的时间来完成任务。请注意,该恒定时间是数组更新/查找的几倍(请参见two和的答案)。因此,除了常量(根据hashmap实现、机器、VM等的不同而有所不同)之外,您无法获得比您发布的代码快得多的速度。如果您确实需要10%的额外性能,那么在硬件/软件/输入数据上建立一个基准,尽可能接近您的预期部署,并对其进行优化

看起来您正在增加额外的开销,不确定这是否会改善它。“使用集合的速度优势”-您这里所说的集合是什么意思?在代码中,
collection
似乎只是一个
Map
。此外,您不必设置Integer.valueOf,还有一个东西叫做自动装箱。“collection”没有containsKey(),put()。。。它看起来像一张地图。此外,您还可以跳过containsKey()步骤,因为如果元素不在映射中,get()将返回null。您无法在小于O(N)的情况下找到模式,因为您必须计算所有数字,以查看遇到的频率最高。使用映射(HashMap)的好处是,您可以对映射的每个元素进行固定时间(O(1))访问,就像通过索引访问数组元素一样(但速度较慢),但与数组不同的是,您只需要为不同的键值对使用内存。没有这种方法-O(n)是此问题的下限如果在计算过程中,您检查了if
currentMaxCount secondBestMaxCount>elementsRemaining
以查看是否值得继续遍历数组,这是否会使(