How can I improve this code for Project Euler 7?

后端 未结 4 659
悲哀的现实
悲哀的现实 2021-01-27 02:29

By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

What is the 10 001st prime number?

My solution:



        
相关标签:
4条回答
  • 2021-01-27 03:01

    The following solution checks only the odd numbers to be prime, but it counts 2 as prime from the beginning:

    public class A {
    
        static int N = 10001;
    
        private static boolean isOddPrime(long x) {
    
            for ( int i = 3 ; i*i <= x ; i+=2 ) {
                if ( x % i == 0 ) {
                    return false;
                }               
            }
            return true;
        }
    
        public static void main(String[] args) throws Exception {
            long start = System.nanoTime();
            int x;
            int i = 2;      // 3 is the 2nd prime number
            for ( x = 3 ; ; x+=2 ) {
                if ( isOddPrime(x) ) {              
                    if ( i == N )
                        break;
                    i++;
                }
            }
            System.out.println(x);
    
            long stop = System.nanoTime();
            System.out.println("Time: " + (stop - start) / 1000000 + " ms");
        }
    }
    

    Output:

    104743
    Time: 61 ms
    
    0 讨论(0)
  • 2021-01-27 03:14

    I would comment, but I just joined.

    You don't have to check every number between 1 and a numbers square root for potential divisors, you just have to check all previous primes (assuming you start at 1 and iterate up), as any other divisor that is not prime will itself be divisible by a prime of a lower value. the higher the number of primes, the more checks against non prime numbers this saves. the example is in C# but that's more to demonstrate the concept.

        //store found primes here, for checking subsequent primes
        private static List<long> Primes;
        private static bool IsPrime(long number)
        {
            //no number will have a larger divisor withou some smaller divisor
            var maxPrime = Math.Sqrt(number);
    
            // takes the list of primes less than the square root and 
            //     checks to see if all of that list is not evenly 
            //     divisible into {number}
            var isPrime = Primes
                .TakeWhile(prime => !(prime > maxPrime))
                .All(prime => number % prime != 0);
            if (isPrime)
                Primes.Add(number);
            return isPrime;
        }
    
        private static long GetNthPrime(int n)
        {
            //reset primes list to prevent persistence
            Primes = new List<long> { 2, 3, 5, 7 };
    
            //prime in starting set
            if (Primes.Count >= n)
            {
                return Primes[n - 1];
            }
    
            //iterate by 6 to avoid all divisiors of 2 and 3 
            //  (also have to check i + 2 for this to work)
            //  similar to incrementing by 2 but skips every third increment 
            //  starting with the second, as that is divisible by 3
            for (long i = 11; i < long.MaxValue; i += 6)
            {
                // only check count if is prime
                if ((IsPrime(i) && Primes.Count >= n) || (IsPrime(i + 2) && Primes.Count >= n))
                {
                    break;
                };
            }
            //return end of list
            return Primes[n - 1];
        }
    
    0 讨论(0)
  • 2021-01-27 03:17

    You need to test the number against every prime less than its square root to ensure it is prime.

    You're only testing against 2,3 and 5.

    Because storing all the primes is not always space-feasable, a common technique is to test for 2, and then test all odd numbers starting at 3. This requires a loop.

    consider:

    boolean isPrime(long n) {
        if (n < 2) return false;
        if (n == 2) return true;
        if (n % 2 == 0) return false;
        if (n < 9) return true;
        if (n % 3 == 0) return false;
        long max = (long)(Math.sqrt(n + 0.0)) + 1;
        for (int i = 5; i <= max; i += 6) {
            if (n % i == 0) return false;
            if (n % (i + 2) == 0) return false;
        }
        return true;
    }
    
    0 讨论(0)
  • 2021-01-27 03:19

    A number p is prime if it only divides by itself and 1. You are checking only for divison by 2, 3 and 5. This is not enough. Check for every number till p / 2, or better till sqrt(p).

    0 讨论(0)
提交回复
热议问题