Java eratosthenes筛的改进,时空复杂度检查

Java eratosthenes筛的改进,时空复杂度检查,java,time-complexity,primes,sieve-of-eratosthenes,space-complexity,Java,Time Complexity,Primes,Sieve Of Eratosthenes,Space Complexity,我理解“eratosthenes筛”算法的时间复杂度为logn。我已经修改了这个算法,使我的筛子总是大小为100。如果我找不到下一个素数,我会继续循环下100个数字。我如何解释getNthPrime和getNextPrime方法的时间复杂性和空间复杂性 片段: public class PrimeUtil { private static final boolean COMPOSITE = true; private static final int DEFAULT_SIZE

我理解“eratosthenes筛”算法的时间复杂度为logn。我已经修改了这个算法,使我的筛子总是大小为100。如果我找不到下一个素数,我会继续循环下100个数字。我如何解释getNthPrime和getNextPrime方法的时间复杂性和空间复杂性

片段:

public class PrimeUtil {

    private static final boolean COMPOSITE = true;
    private static final int DEFAULT_SIZE = 100;

    // cache of primes.
    public final List<Integer> primes;
    public int cachedMaxPrime;

    public PrimeUtil() {
        primes = new ArrayList<Integer>();
        // initial seed
        primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13));
        cachedMaxPrime = primes.get(primes.size() - 1);
    }

    private void validate(int n) {
        if (n <= 0) { 
            throw new IllegalArgumentException("Expecting a non-zero value");
        }
    }

    public synchronized int getNthPrime(int nThPrime) {
        validate(nThPrime); 

        if (nThPrime <= primes.size()) {
            return primes.get(nThPrime - 1);
        }
        int n = DEFAULT_SIZE; // find all primes for next 100 numbers.

        while (primes.size() < nThPrime) {

            computePrimesUptoN(n);  
            n += DEFAULT_SIZE; // find all primts for next 100 numbers.
        } 
        return primes.get(nThPrime - 1);
    } 

    public synchronized int getNextPrime(int prime) {
        validate(prime); 

        int primeIndex = Collections.binarySearch(primes, prime);
        if (primeIndex != -1 && primeIndex != (primes.size() - 1)) {
            return primes.get(primeIndex + 1);
        }
        int prevSize = primes.size();
        int n = DEFAULT_SIZE; // adding cachedMaxPrime to DEFAULT_SIZE is a tiny optimization, nothing else.


        while (primes.size() == prevSize) {

            computePrimesUptoN(n);
            n += DEFAULT_SIZE;
        } 
        return primes.get(primeIndex + 1);
    }

    private List<Integer> computePrimesUptoN(int n) {
        boolean[] composites = new boolean[n - cachedMaxPrime]; // 
        int root = (int)Math.sqrt(n);                           // root is sqrt(50) ie 7.

        for (int i = 1; i < primes.size() && primes.get(i) <= root; i++) { // will loop until prime = 7.
            int prime  = primes.get(i); // first prime: 3

            int firstPrimeMultiple = (cachedMaxPrime + prime) -  ((cachedMaxPrime + prime) % prime); 
            if (firstPrimeMultiple % 2 == 0) {
                firstPrimeMultiple += prime; 
            }

            filterComposites(composites, prime, firstPrimeMultiple, n);
        }

        // loop through all primes in the range of max-cached-primes upto root.
        for (int prime = cachedMaxPrime + 2; prime < root; prime = prime + 2) {
            if (!composites[prime]) {
                // selecting all the prime numbers.
                filterComposites(composites, prime, prime, n);
            }
        }

        for (int i = 1; i < composites.length; i = i + 2) {
            if (!composites[i]) {
                primes.add(i + (cachedMaxPrime + 1));
            }
        }

        cachedMaxPrime = primes.get(primes.size() - 1);
        return primes;
    }

    private void filterComposites(boolean[] composites, int prime, int firstMultiple, int n) {
        for (int multiple = firstMultiple; multiple < n; multiple += prime + prime) {
            composites[multiple - (cachedMaxPrime + 1)] = COMPOSITE;
        } 
    }
}