查找列表中存在超过k次的所有元素的最佳方法

时间:2016-03-29 14:42:35

标签: java array-algorithms

我刚遇到一个问题,我想知道解决这个问题的最佳方法是什么。

我有一份清单

L = [[1, 2, 3, 4, 5, 6, 7], [2, 4, 6, 8, 10, 12], [3, 6, 9, 12, 15], ....]

假设 L 的大小 n ,找到所有存在的元素 k 或更多次的最佳方法是什么在 L

例如,如果k = 2,那么我应该得到 [2, 3, 4, 6, 12]

3 个答案:

答案 0 :(得分:3)

  

假设L的大小为n,那么在L中找到所有存在k次或多次的元素的最佳方法是什么?

传统方式是迭代每个列表一次并在HashMap<Integer, Integer>中收集时间值(其中key是数字,值是次数)。然后,您只需从地图中收集值为k或更多的所有键:

 public static List<Integer> getResultListByMap(List<List<Integer>> inputList, int k) {
    Map<Integer, Integer> times = new HashMap<>();
    for (List<Integer> integers : inputList) {
        for (Integer integer : integers) {
            if (times.keySet().contains(integer)) {
                times.put(integer, times.get(integer) + 1);
            } else {
                times.put(integer, 1);
            }
        }
    }

    List<Integer> result = new ArrayList<>();
    for (Map.Entry<Integer, Integer> entry : times.entrySet()) {
        if (entry.getValue() >= k) {
            result.add(entry.getKey());
        }
    }
    return result;
}

result列表包含列表k或更多次列出的所有数字

更新:好的,我已经知道您已经使用HashMap方法而且对您来说速度很慢。我编写了一个带有Java 8 Stream API功能的算法,它使用列表连接,排序和从并行性中获得奖励:

public static List<Integer> getResultListBySort(List<List<Integer>> inputList, int k) {
    List<Integer> newList = inputList.parallelStream()
            .flatMap(l -> l.parallelStream()).sorted().collect(Collectors.toList());

    List<Integer> result = new ArrayList<>();

    Integer prev = null;
    int sum = newList.get(0);
    for (Integer integer : newList) {
        if (integer.equals(prev)) {
            sum++;
        } else {
            if (sum >= k) {
                result.add(integer);
            }
            sum = 1;
        }
        prev = integer;
    }
    return result;
}

2000 x 2000问题大小快了两倍 - 2000个列表有2000个元素(现在只需半秒钟就能在我的电脑上获得结果列表)

Benchmark                       Mode  Samples  Score  Score error  Units
c.c.b.MyBenchmark.testMap       avgt       20  0,972        0,030   s/op
c.c.b.MyBenchmark.testSorted    avgt       20  0,534        0,005   s/op

答案 1 :(得分:0)

这完全取决于在L上执行的操作的频率。考虑到你偶尔做这个操作然后用O(n_1 + n_2 + n_3 + ... + n_n)找到结果就可以了时间复杂性。即,通过迭代数组和计数来找出每一次。如果它是一个频繁的操作,为什么不对数组数组进行排序或为什么不使用缓存。我认为最好的方法完全取决于您的使用情况。

答案 2 :(得分:0)

维护一个额外的count数组,用于存储完全遍历的元素数。然后,在更新元素计数的同时遍历列表,并在更新元素的计数等于k时,将其添加到最终答案列表,该列表最初为空。但要实现这一点,您应该知道给定数组中的最大元素。

final_answer = []
count = [0 for i in range(max_el)] # put very large number here e.g. 1000
for sublist in L:
    for element in sublist:
        count[element] += 1
        if count[element] == k:
            final_list.append(element)

打印(final_answer)