【发布时间】:2019-05-22 23:23:28
【问题描述】:
我正在解决 Codility 问题CountSemiprimes: Count the semiprime numbers in the given range [a..b]。
任务说明
素数是一个正整数 X,它正好有两个不同的除数:1 和 X。前几个素数是 2、3、5、7、11 和 13。
半素数是一个自然数,它是两个(不一定不同)素数的乘积。前几个半素数是 4、6、9、10、14、15、21、22、25、26。
给定两个非空数组 P 和 Q,每个数组由 M 个整数组成。这些数组表示关于指定范围内的半素数的查询。
查询 K 要求您在 (P[K], Q[K]) 范围内找到半素数的个数,其中 1 ≤ P[K] ≤ Q[K] ≤ N。
为以下假设编写一个有效的算法:
- N 是 [1..50,000] 范围内的整数;
- M是[1..30,000]范围内的整数;
- 数组 P、Q 的每个元素都是 [1..N] 范围内的整数; P[i] ≤ Q[i]。
我的解决方案
我目前的分数是 66%,问题是大数据集的性能:
- 大随机数,长度 = ~30,000
- 所有最大范围
测试表明,它应该需要大约 2 秒,但我的解决方案需要 7 秒。
这是我目前的解决方案
class Solution {
private static List<Integer> getPrimes(int max) {
List<Integer> primes = new ArrayList<>(max / 2);
for (int i = 0; i < max; i++)
if (isPrime(i))
primes.add(i);
return primes;
}
private static boolean isPrime(int val) {
if (val <= 1)
return false;
if (val <= 3)
return true;
for (int i = 2, sqrt = (int)Math.sqrt(val); i <= sqrt; i++)
if (val % i == 0)
return false;
return true;
}
private static boolean[] getSemiPrimes(int N) {
List<Integer> primes = getPrimes(N);
boolean[] semiPrimes = new boolean[N + 1];
for (int i = 0; i < primes.size(); i++) {
if (primes.get(i) > N)
break;
for (int j = i; j < primes.size(); j++) {
if (primes.get(j) > N || N / primes.get(i) < primes.get(j))
break;
int semiPrime = primes.get(i) * primes.get(j);
if (semiPrime <= N)
semiPrimes[semiPrime] = true;
}
}
return semiPrimes;
}
public static int[] solution(int N, int[] P, int[] Q) {
boolean[] semiPrimes = getSemiPrimes(N);
int[] res = new int[P.length];
for (int i = 0; i < res.length; i++)
for (int j = P[i]; j <= Q[i]; j++)
if (semiPrimes[j])
res[i]++;
return res;
}
}
关于提高性能的任何想法?我的最后一个是删除 Set 以使用数组保存半素数。它帮助我解决了几个性能测试。
【问题讨论】:
-
你应该使用类似 Eratosthenes 的筛子来生成素数。我认为这应该更快。
-
@marstran 我已经检查过了。
for循环到sqrt(n)是找到所有素数的最有效方法[0...n] -
这绝对不是找到 n 以内的所有素数的最有效方法。检查单个值是否为质数效果更好,但有一些方法可以使其更快,例如使用
i += 2而不是i++,或者只使用check divisibility for values in the form6*i ± 1。筛子始终是生成素数列表的最佳方法。您错误地完成了基准测试 -
@phuclv 无论如何,这不会增加3倍
-
@oleg.cherednik 直到
sqrt(n)的for循环可能是确定一个数是否为素数的最快方法。但是,生成素数列表不是最快的。为此目的,筛子要快得多。
标签: java algorithm performance