假设 L 的大小为 n,那么找出在 L 中出现 k 次或更多次的所有元素的最佳方法是什么?
传统方式是遍历每个列表一次,并在HashMap<Integer, Integer> 中收集次数值(其中key 是数字,value 是次数)。然后你只需要从 map 中收集所有值为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 个元素的两倍(现在只需半秒即可在我的 PC 上获得结果列表)
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