优化运行时以查找第n个素数

时间:2014-07-29 21:59:25

标签: java optimization runtime

这是一个Java程序,它在给定范围内找到第n个素数。 可输入的最大范围是1-1500000。 代码输出对于所有可能的测试用例都是正确的,但必须针对运行时进行优化。 此代码中可以应用哪些优化技术?

import java.io.*;
class prime
{
    public static void main(String[] args)throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String m1,m2,m;
        int n1=0,n2=0,n=0;
        try
        {
//input as string instead of integer because errors must be displayed only after all the values have been input

        m1=br.readLine();   //range minimum value
        m2=br.readLine();   //range max value
        m=br.readLine();    //nth value in range
        n1=Integer.parseInt(m1);
        n2=Integer.parseInt(m2);
        n=Integer.parseInt(m);
        if(n1<0||n2>1500000||n1>n2||n==0)
                throw new Exception();
        }
        catch(Exception e)
        {
            System.out.println("Invalid Input");
            System.exit(0);
        }
        int k=n1,count=0,count1=0;
        while(k<=n2&&count1<=n)
        {
            count=0;
            for(int i=1;i<=k;i++)
            {
                if(k%i==0)
                    count++;
            }
            if(count==2)
            {
                count1++;
            }
            k++;
        }
        if(count1==n)
        {
            System.out.println(k);
            System.exit(0);
        }
        if(count1<n)
        {
            System.out.println("No prime number is present at this index");
            System.exit(0);
        }

    }
}

3 个答案:

答案 0 :(得分:0)

检查2和k的平方根之间的除数。如果你找不到,你就找到了一个黄金。

    int k=n1,count1=0;
    while(k<=n2&&count1<=n)
    {
        boolean isPrime = true;
        for(int i=2;i <= Math.sqrt(k) ;i++)
        {
            if(k%i==0) 
            {
                isPrime = false;
                break;
            }
        }
        if (isPrime)
             count1++;
        k++;
    }

此外,您可以明确处理2并跳过其他偶数。

答案 1 :(得分:0)

  1. 不要测试&#34;正好有2个除数&#34;,test&#34;不能被1和1以外的数字整除&#34;。

  2. 不要将所有值&lt; = k作为除数进行测试,测试所有值&lt; = sqrt(k)。

    (如果一个数字可以被大于sqrt(k)的数字整除,那么除法的结果也是一个除数,但是之前已经找到了)

  3. 也许重用已经计算过的素数;您只需要将素数作为可能的除数进行测试。但是你需要小心。如果你是在9999-9999范围内搜索,计算所有较小的素数是没有意义的,但是如果范围是1-9999,它会减少你必须进行的检查次数。您可以将两种方法和小于n1的测试数字结合起来&#34; normal&#34;使用你已经找到的素数来测试所有较大的除数。

  4. 您的循环可以像这样重写以应用1.和2。:

    int k=Math.max(2, n1); // 0 and 1 are no prime
    int count1 = 0;
    while(k <= n2 && count1 <= n) {
        final int sqrt = (int) Math.sqrt(k);
        count1++; // asume it's a prime
        for(int i = 2; i <= sqrt; i++) {
            if(k % i == 0) {
                // divisible by number other than 1 and itself -> not a prime
                count1--;
                break;
            }
        }
        k++;
    }
    

    这会将运行时间从O((n2)² - (n1)²)缩短为

    O((n2)^1.5 - (n1)^1.5)

答案 2 :(得分:0)

由于您的最大值是有限的,因此保留一个2到1229(1229²= 1510441)的素数表是有意义的,并依次尝试它们,直到数字小于素数的平方。 2可以不经分割地进行测试。您还可以存储正方形的表格。

      2      3      5      7     11     13     17     19     23     29 
     31     37     41     43     47     53     59     61     67     71 
     73     79     83     89     97    101    103    107    109    113 
    127    131    137    139    149    151    157    163    167    173 
    179    181    191    193    197    199    211    223    227    229 
    233    239    241    251    257    263    269    271    277    281 
    283    293    307    311    313    317    331    337    347    349 
    353    359    367    373    379    383    389    397    401    409 
    419    421    431    433    439    443    449    457    461    463 
    467    479    487    491    499    503    509    521    523    541 
    547    557    563    569    571    577    587    593    599    601 
    607    613    617    619    631    641    643    647    653    659 
    661    673    677    683    691    701    709    719    727    733 
    739    743    751    757    761    769    773    787    797    809 
    811    821    823    827    829    839    853    857    859    863 
    877    881    883    887    907    911    919    929    937    941 
    947    953    967    971    977    983    991    997   1009   1013 
   1019   1021   1031   1033   1039   1049   1051   1061   1063   1069 
   1087   1091   1093   1097   1103   1109   1117   1123   1129   1151 
   1153   1163   1171   1181   1187   1193   1201   1213   1217   1223 
   1229