找到阵列中第N个最常见的数字

时间:2012-06-10 02:20:28

标签: algorithm frequency

Find the nth most frequent number in array.
(There is no limit on the range of the numbers)

我认为我们可以

(i)使用C ++中的地图存储每个元素的出现

(ii)在元素的出现(或频率)的线性时间内构建最大堆,然后提取到第N个元素, 每次提取需要log(n)时间进行堆积。

(iii)我们将获得第N个最频繁数字的频率

(iv)然后我们可以通过哈希进行线性搜索,找到具有此频率的元素。

时间 - O(NlogN) 空间 - O(N)

有没有更好的方法?

4 个答案:

答案 0 :(得分:8)

它可以在线性时间和空间中完成。令T为输入数组中元素的总数,我们必须从中找到第N个最常见的数字:

  1. 在地图中计算并存储T中每个数字的频率。设M是数组中不同元素的总数。所以,地图的大小是M. - O(T)
  2. 使用Selection algorithm在地图中查找第N个最大频率。 - O(M)
  3. 总时间= O(T)+ O(M)= O(T)

答案 1 :(得分:3)

你的方法基本上是正确的。如果使用它表示的数字标记构造堆的每个顶点,则可以避免最终散列搜索。此外,在构建堆时,可以不断地监视堆的第五个元素,因为在某些时候,您可以进入结果不再变化的情况,并且可以删除其余的计算。但是这可能不会使算法在一般情况下更快,甚至在特殊情况下也许不会。所以你正确回答了自己的问题。

答案 2 :(得分:1)

这取决于您是否需要最有效或最易于编写的方法。

1)如果你知道所有数字都是从0到1000,你只需要制作1000个零(出现)的数组,循环遍历你的数组并增加正确的出现位置。然后排序这些出现并选择第N个值。

2)你有一个独特物品的“包”,你循环你的数字,检查这个数字是否在一个袋子里,如果没有,你添加它,如果它在这里,你只是增加出现次数。然后从中选择第N个最小数字。

Bag可以是线性数组,BST或Dictionary(哈希表)。

问题是“第N次最频繁”,所以我认为你无法避免排序(或聪明的数据结构),所以最好的复杂性不能比O(n * log(n)更好))。

答案 3 :(得分:1)

仅用Java8编写了一个方法:这不是有效的解决方案。

  • 为每个元素创建频率图
  • 根据相反的值对地图内容进行排序。
  • 跳过第(N-1)个元素,然后找到第一个元素

    private static Integer findMostNthFrequentElement(int[] inputs, int frequency) {
        return Arrays.stream(inputs).boxed()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .skip(frequency - 1).findFirst().get().getKey();
    }