【问题标题】:find nth prime number找到第 n 个素数
【发布时间】:2013-01-22 10:40:04
【问题描述】:

我在下面编写了以下代码来查找第 n 个素数。这可以在时间复杂度上提高吗?

说明:

ArrayList arr 存储计算的素数。一旦 arr 达到大小“n”,循环退出,我们检索 ArrayList 中的第 n 个元素。在计算素数之前将数字2和3相加,并检查从4开始的每个数字是否为素数。

public void calcPrime(int inp) {
    ArrayList<Integer> arr = new ArrayList<Integer>(); // stores prime numbers 
                                                      // calculated so far
    // add prime numbers 2 and 3 to prime array 'arr'
    arr.add(2); 
    arr.add(3);

    // check if number is prime starting from 4
    int counter = 4;
     // check if arr's size has reached inp which is 'n', if so terminate while loop
    while(arr.size() <= inp) {
        // dont check for prime if number is divisible by 2
        if(counter % 2 != 0) {
            // check if current number 'counter' is perfectly divisible from 
           // counter/2 to 3
            int temp = counter/2;
            while(temp >=3) {
                if(counter % temp == 0)
                    break;
                temp --;
            }
            if(temp <= 3) {
                arr.add(counter);
            }
        }
        counter++;
    }

    System.out.println("finish" +arr.get(inp));
    }
}

【问题讨论】:

  • 请给我们一个直观的描述你的程序做什么,或者至少提供cmet。给我们一段代码并要求我们对其进行分析,这使得任何人都很难弄清楚它的含义。
  • 它是否会提高计算复杂度可能还有待商榷,但埃拉托色尼的筛子还是要一点。
  • @templatetypedef:将 cmets 添加到代码中。
  • 另外,最好先搜索SO:stackoverflow.com/tags/primes/hot?filter=year

标签: java performance algorithm complexity-theory primes


【解决方案1】:

您可以采取一些措施来加快速度:

  1. 从 5 开始计数器并将其递增 2 而不是 1,然后不要在循环中检查 mod 2。
  2. 不是从 counter / 2 开始 temp,而是从第一个奇数
  3. 将温度降低 2。

我不确定它是否算作提高复杂度,但上面的 (2) 将从 O(n^2) 变为 O(n*sqrt(n))

【讨论】:

  • tempsqrt 向下测试效率非常低。我怀疑它甚至会使复杂性变得更糟。
  • @Will 确实如此。我没有详细分析它,但是单独的较大因子至少是较小因子四倍的半素数给出了额外的log log n 因子。不过,我预计在很长一段时间内,常数因子的放缓会更糟。
  • @Daniel 凭经验 ideone.com/iNxOrC 确实倒计时代码似乎在m^1.5 中运行,其中 m 是上限。实际运行时间的比率为2.6x ... 3.6x 并且还在恶化,上限为 100k ... 120 万。 m^1.5 用于倒计时代码实际上是有道理的 - 没有提前截止,所以就好像以低于 sqrt 的所有几率测试 每个奇数。在计算时,非素数赔率的成本最多与素数相同(如 M. O'Neill 所示),给出m^1.5/log(m)
  • @Will “提前截止”是什么意思?你除数直到找到第一个除数或达到极限,无论你是向上还是向下数,在这方面,两种方式都是相似的。不过,倒计时,您通常距离第一个除数的距离要长得多。我有点期望它平均为Θ(√n)(所以经验m^1.5 适合),但我没有看到一个简单的方法来证明它(最接近√n 的除数比最小的主要除数更难掌握)。
  • @Daniel 这就是我的意思,是的,更长的路几乎是“一路”。当然,这在任何方面都不严格。尝试在 2..n 范围内为随机选择的复合材料找到最大因子的“预期值”,达到这种效果(平均而言,这将是我们的截止点,倒计时)。 nsqrt(n),我希望不会有太大影响。
【解决方案2】:

是的。

您的算法进行 O(n^2) 操作(也许我不准确,但似乎如此), 其中 n 是结果。

http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes算法采用O(ipn* log(log(n)))。您只能在其中执行 inp 步,并假设 n = 2ipn*ln(ipn)n 应该大于 ipn-prime。 (我们知道素数的分布http://en.wikipedia.org/wiki/Prime_number_theorem

无论如何,你可以改进现有的解决方案:

public void calcPrime(int inp) {
    ArrayList<Integer> arr = new ArrayList<Integer>();
    arr.add(2);
    arr.add(3);

    int counter = 4;

    while(arr.size() < inp) {
        if(counter % 2 != 0 && counter%3 != 0) {
            int temp = 4;
            while(temp*temp <= counter) {
                if(counter % temp == 0)
                    break;
                temp ++;
            }
            if(temp*temp > counter) {
                arr.add(counter);
            }
        }
        counter++;
    }

    System.out.println("finish" +arr.get(inp-1));
    }
}

【讨论】:

  • 你能告诉我这是如何工作的,特别是你为什么要使用 temp*temp 进行检查?那将检查计数器是否可被 16,25,36 整除..
  • 他根据计数器检查 temp*temp,因为这意味着 temp
  • 什么是n?什么是ipninpinp 吗?这是埃拉托色尼的筛子吗?
  • arr不需要加1吗?否则求第一个素数会得到 2 而不是 1。
【解决方案3】:
public static void Main()
    {
        Console.Write("Enter a Number : ");
        int num;
        int[] arr = new int[10000];
        num = Convert.ToInt32(Console.ReadLine());
        int k;
        k = 0;
        int t = 1;
        for (int j = 1; j < 10000; j++)
        {
            for (int i = 1; i <= j; i++)
            {
                if (j % i == 0)
                {
                    k++;
                }
            }
            if (k == 2)
            {
                arr[t] = j;
                t++;
                k = 0; 
            }
            else
            { 
                k = 0;
            } 
        }
        Console.WriteLine("Nth Prime number. {0}", arr[num]);
        Console.ReadLine();
    }

【讨论】:

  • 您能否说明改进之处?
  • 如何 [improve] time complexity [of find the nth prime over counting primes identified by trial division]?
【解决方案4】:
    System.out.println("Enter The number n: ");
    Scanner scanner = new Scanner(System.in);

    int n = scanner.nextInt();

    int x = 0;
    String prime = "";

    for (int i = 1; i <= n; i++) {

        int counter = 0;

        for (x = i; x >= 1; x--) {

            if (i % x == 0) {
                counter++;
            }
        }

        if (counter == 2){
            prime =  prime + i + " ";
        }

    }

    System.out.println(prime);
}

}

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
相关资源
最近更新 更多