我使用下面的程序来找到前n个素数(在下面的程序中它是从2到n)。我们可以用单个for循环编写一个程序吗?我也试过递归方法,但它对我不起作用。
T(0,...,0)
答案 0 :(得分:1)
我认为你不能把它减少到一个循环。但是你可以像Luca提到的那样改进你的代码。
public class PrimeFinder {
private final List<Integer> primes;
private final int primeCapacity;
public PrimeFinder(final int primeCapacity) {
if (primeCapacity < 3) {
throw new IllegalArgumentException("Tkat is way to easy.");
}
this.primeCapacity = primeCapacity;
primes = new ArrayList<>(primeCapacity);
primes.add(2);
}
public void find() {
final Index currentNumber = new Index();
while (primes.size() < primeCapacity) {
if (!primes.stream().parallel().anyMatch(prime -> (currentNumber.value % prime) == 0)) {
primes.add(currentNumber.incremet());
} else {
currentNumber.incremet();
}
}
}
public List<Integer> getPrimes() {
return primes;
}
private class Index {
public int value = 3;
public int incremet() {
return value++;
}
}
public static void main(String[] args) {
PrimeFinder primeFinder = new PrimeFinder(100000);
final long start = System.currentTimeMillis();
primeFinder.find();
final long finish = System.currentTimeMillis();
System.out.println("Score after " + (finish - start) + " milis.");
primeFinder.getPrimes().stream().forEach((prime) -> {
System.out.println(prime);
});
}
}
这里的主要规则很简单,如果给定的数字没有明显除以您已经找到的任何素数,那么它就是素数。
P.S。不要忘记primes.strem()....
也是循环,所以它不是一个循环代码。
P.S.S。你可以进一步减少这一点。
答案 1 :(得分:0)
要了解算法的复杂性,您不必计算内部循环的数量,而是计算迭代元素的次数。要提高算法的性能,您需要调查是否存在一些不必要的迭代。 在你的情况下,当你这样做 for(int i = 2; i&lt; = num / 2; i ++)你正在测试你的num对不必要的值。例如:如果一个数字可以被4整除,那么它也将是2。
当你为(int i = 2; i&lt; = num / 2; i ++)做num = 11时 我将假设值2,3,4,5。 4这里是一个没有趣的数字,代表了一个可以避免的迭代。
无论如何根据维基百科,Eratosthenes的筛子是找到所有较小素数的最有效方法之一。
public class PrimeSieve {
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
// initially assume all integers are prime
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
}
}
}
// count primes
int primes = 0;
for (int i = 2; i <= N; i++) {
if (isPrime[i]) primes++;
}
System.out.println("The number of primes <= " + N + " is " + primes);
}
}
答案 2 :(得分:0)
我不知道如何使用单个循环来解决您的问题,但我确实看到了两个可以降低复杂性的地方:
缓存找到的素数并使用这些素数来判断数字是否为素数。例如,要确定11是否为素数,您只需将其除以2,3,5,7而不是2,3,4,5,6,...... 10
你不需要检查到num / 2,你只需要检查直到num的平方根。例如,对于10,您只需要检查2,3而不是2,3,4,5。因为如果数字n不是素数,则n = a * b,其中a或b小于n的平方根x。如果a是较小的一个,知道n可以除以a足以判断n不是素数。
所以结合1&amp; 2,你可以提高你的循环效率:
public static void main(String[] args) {
// Prime numbers in a range
int range = 15;
int num = 1;
int count = 0;
boolean prime = true;
ArrayList<Integer> primes = new ArrayList<>(range);
while (num < range) {
num = num + 1;
prime = true;
int numSquareRoot = (int) Math.floor(Math.pow(num, 0.5));
for (Integer smallPrimes : primes) {// only need to divide by the primes smaller than num
if (numSquareRoot > numSquareRoot) {// only need to check till the square root of num
break;
}
if (num % smallPrimes == 0) {
prime = false;
break;
}
}
if (prime) {
System.out.println(num);
primes.add(num);// cache the primes
}
}
}