Я решаю проблему Codility CountSemiprimes: Подсчитать числа полупростых в заданном диапазоне [a..b] .
Описание задачи
A штрих - это положительное целое число X, которое имеет ровно два различных делителя: 1 и X. Первые несколько простых целых чисел - это 2, 3, 5, 7, 11 и 13.
A semiprime - натуральное число, являющееся произведением двух (не обязательно различных) простых чисел.Первые несколько полупростых чисел: 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%, и проблема заключается в выполнении для большого набора данных:
- большой случайный, длина = ~ 30000
- все максимальные диапазоны
Тест говорит, что это займет около 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
для хранения полупростых чисел с массивом.Это помогло мне решить пару тестов производительности.