【问题标题】:Return all prime numbers smaller than M返回所有小于 M 的素数
【发布时间】:2011-07-17 21:01:35
【问题描述】:

给定一个整数 M。返回所有小于 M 的素数。

给出一个尽可能好的算法。需要考虑时间和空间复杂度。

【问题讨论】:

    标签: algorithm primes


    【解决方案1】:

    埃拉托色尼筛法是一个很好的起点。

    http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

    【讨论】:

    • 还有其他易于理解且不需要 O(n) 空间的筛子。或者你只是一遍又一遍地做一个恒定数量的数字。例如。您希望所有质数低于 10000,然后分批执行 100 或 1000 以减少空间使用,然后只保存质数。
    • O(n) 空间是很大的空间复杂度,如果 N 更高,可能是 20 亿或更多。阿特金筛子是最好用的。
    【解决方案2】:

    一些额外的性能提示:

    1. 您只需要测试直到M 的平方根,因为每个合数至少有一个质因数小于或等于其平方根
    2. 您可以在生成已知素数时缓存它们,并仅针对此列表中的数字测试后续数字(而不是 sqrt(M) 下面的每个数字)
    3. 您显然可以跳过偶数(当然,2 除外)

    【讨论】:

    • 3.好吧,你不应该放弃所有这些!你不应该放弃 2 ;-)
    • 我认为第一句话是错误的。例如 N = 120。113 是素数 sqrt (N)。
    • 我不确定你想说什么。当然,可能有(不相关的)素数大于 N 的平方根,但这并不能告诉我们任何有用的信息。关键是每个合数至少有一个质因数小于或等于它的平方根,你只需要找到一个这样的因数来证明 N 是合数(即没有必要继续检查)。这就是第一句话的重点。
    • 对不起。我认为您的答案可能很短,看起来像是评论而不是完整的答案。当我阅读 Eratosthenes 的 Wiki Sieve 时,我了解您的提示。但是因为你的答案是我读到的第一件事,所以我不明白你在说什么。
    • 您是对的,但是您需要了解上下文才能应用该事实。我并不是说你的答案是错误的,但是直到我从另一个答案中得到上下文我才明白它,我只是建议稍微改进你的答案,以便其他用户更好地理解,例如我把你的 N 与OP M. 还要意识到,即使你的答案是被接受的,来自 Andrew 的答案也是投票最多的,因为它可以为寻找答案的其他用户提供正确的上下文。
    【解决方案3】:

    usual answer 是实现Sieve of Eratosthenes,但这实际上只是查找所有小于 N 的素数列表的解决方案。如果您想要primality tests 用于特定数字,对于大的数有更好的选择数字。

    【讨论】:

      【解决方案4】:

      Eratosthenes 的筛子很好。

      【讨论】:

        【解决方案5】:

        我是 C# 的新手程序员(也是 S.O. 的新手),所以这可能有点冗长。不过,我已经对此进行了测试,并且可以正常工作。

        这是我想出的:

        for (int i = 2; i <= n; i++)
        {
            while (n % i == 0)
            {
                Console.WriteLine(i.ToString());
                n /= i;
            }
        }
        Console.ReadLine();
        

        【讨论】:

          【解决方案6】:

          π(n) 计算小于或等于 n 的素数。 Pafnuty Chebyshev 已经证明,如果

          limn→∞ π(n)/(n/ln(n))

          存在,它是1。实际上有很多近似等于π(n)的值,如表所示。

          它为这种数字格式提供了正确的素数数量。我希望这会有所帮助。

          【讨论】:

          • 这没有回答问题。
          【解决方案7】:

          您可以使用自下而上的动态编程方法(称为埃拉托色尼筛法)来做到这一点 基本上,您创建一个所有数字的布尔缓存,直到 n 并将每个数字的倍数标记为 not_prime。 进一步优化可以通过只检查到 sqrt(n) 来获得,因为任何合数都会有至少一个除数小于 sqrt(n)

              public int countPrimes(int n) {
              if(n==0){
                  return 0;
              }else{
                  boolean[] isPrime=new boolean[n];
                  for(int i=2;i<n;i++){
                      isPrime[i]=true;
                  }
          
                  /* Using i*i<n instead of i<Math.sqrt(n)
                   to avoid the exepnsive sqrt operation */
                  for(int i=2;i*i<n;i++){
                     if(!isPrime[i]){
                         continue;
                     }
                      for(int j=i*i;j<n;j+=i){
                          isPrime[j]=false;
                      }
                  }
          
                  int counter=0;
                  for(int i=2;i<n;i++){
                      if(isPrime[i]){
                          counter++;
                      }
                  }
          
                  return counter;
          
              }
          }
          

          【讨论】:

            【解决方案8】:

            这是我为 Seive of Eratosthenes 开发的。当然,会有更好的实现。

            //找到小于长度的素数个数

            private static int findNumberOfPrimes(int length) {
                int numberOfPrimes = 1;
                if (length == 2) {
                    return 1;
                }
            
                int[] arr = new int[length];
                //creating an array of numbers less than 'length'
                for (int i = 0; i < arr.length; i++) {
                    arr[i] = i + 1;
                }
                //starting with first prime number 2, all the numbers divisible by 2(and upcoming) is replaced with -1
                for (int i = 2; i < arr.length && arr[i] != -1; i++) {
            
                    for (int j = i; j < arr.length; j++) {
                        if (arr[j] % arr[i] == 0) {
                            arr[j] = -1;
                            numberOfPrimes += 1;
                        }
                    }
            
                }
                return numberOfPrimes;
            }
            

            【讨论】:

              【解决方案9】:

              阿特金筛法也是在这种情况下实现的最佳算法,它只需要 O(N) 次操作和 O(N) 空间。算法和伪代码的详细解释请参考https://en.wikipedia.org/wiki/Sieve_of_Atkin

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2014-07-21
                • 2013-05-28
                • 2012-02-19
                • 2016-07-27
                • 1970-01-01
                相关资源
                最近更新 更多