我有一个紧密的循环来搜索互质。列表primeFactors
。它的第n个元素包含n的素数分解的排序列表。我正在使用c
d
和checkIfPrimes
是否是互质
boolean checkIfPrimes(int c, int d, List<List<Integer>> primeFactors) {
List<Integer> common = new ArrayList<>(primeFactors.get(d)); //slow
common.retainAll(primeFactors.get(c));
return (common.isEmpty());
}
primeFactors.get(d).retainAll(primeFactors.get(c))
看起来很有希望,但它会改变我的可重用primeFactors
对象。
创建新对象相对较慢。有没有办法加快这一步?我可以以某种方式利用列表排序的事实吗?我应该使用数组吗?
答案 0 :(得分:2)
您可以使用Collection
快速查找 - 例如a Set
如果您只需要素数而不重复,或Map
如果您还需要每个因素的计数。
基本上,您想知道两个集合的交集是否为空。 Oracle Set tutorial显示了一种计算相交的方法(类似于您已经提到的,在副本上使用retainAll
,但在设置上操作应该更有效)。
答案 1 :(得分:2)
由于您的列表相对较小,并且此操作经常执行,因此您应该避免创建任何新的列表或集合,因为它可能会导致GC的巨大压力。
扫描线性算法
public static boolean emptyIntersection(List<Integer> sortedA, List<Integer> sortedB) {
if (sortedA.isEmpty() || sortedB.isEmpty())
return true;
int sizeA = sortedA.size(), sizeB = sortedB.size();
int indexA = 0, indexB = 0;
int elementA = sortedA.get(indexA), elementB = sortedB.get(indexB);
while (true) {
if (elementA == elementB) {
return false;
} else if (elementA < elementB) {
indexA++;
if (indexA == sizeA)
return true;
elementA = sortedA.get(indexA);
} else {
// elementB < elementA
indexB++;
if (indexB == sizeB)
return true;
elementB = sortedB.get(indexB);
}
}
}
还要考虑使用原始int
s的列表而不是盒装整数,例如: G。来自fastutil图书馆。
答案 2 :(得分:1)
通常你可以使用布尔数组。其中数组的索引是数字,并且当布尔值为true
时,布尔值返回false
。
答案 3 :(得分:1)
您可以采取以下措施:
List<Integer> commonElements =
primeFactors.get(d).stream()
.filter(primeFactors.get(c)::contains)
.collect(Collectors.toList());
一旦你衡量了这个表现,你可以用'parallelStream()'代替上面的'stream()',看看你得到了什么好处。
答案 4 :(得分:1)
设置操作应该比数组操作更快。 只是为了解决问题,请考虑尝试并将性能与流性能进行比较:
final Set<Integer> commonSet;
final Set<Integer> cSet = new HashSet<Integer>();
final Set<Integer> dSet = new HashSet<Integer>();
cSet.addAll(primeFactors.get(c));
dSet.addAll(primeFactors.get(d));
commonSet = dSet.retainAll(cSet);
return (commonSet.isEmpty());
另外,
考虑使用List<Set<Integer>> primeFactors
而不是List<List<Integer>> primeFactors
,因为我怀疑你不这样做
确实有一系列素因子,但实际上有一组素因子。