zoukankan      html  css  js  c++  java
  • 【LeetCode-204】--计算[2,n]的所有质数--

    转载自:https://leetcode-cn.com/problems/count-primes/solution/ji-shu-zhi-shu-by-leetcode-solution/

    统计所有小于非负整数 n 的质数的数量。

    示例 1:

    输入:n = 10
    输出:4
    解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
    示例 2:

    输入:n = 0
    输出:0
    示例 3:

    输入:n = 1
    输出:0

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/count-primes
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    代码路径:

    方法1:

      最简单粗暴的方法,双层遍历,没什么好讲的

      时间复杂度:O(n2)

     1     public static int countPrimes2(int n) {
     2         int count = 0;
     3         for (int i = 2; i < n; i++) {
     4             if (isPrimes(i)) {
     5                 count++;
     6             }
     7         }
     8         return count;
     9     }
    10 
    11     public static boolean isPrimes(int i) {
    12         for (int j = 2; j < i; j++) {
    13             if (i % j == 0) {
    14                 return false;
    15             }
    16         }
    17         return true;
    18     }

     方法2:

      基于方法1的优化,在方法1的isPrimes中存在很多次的冗余的计算,在isPrimes方法中j不需要遍历到i,而只需要遍历到sqrt(n);为什么呢,假设n=12;

    12 = 2 × 6
    12 = 3 × 4
    12 = sqrt(12) × sqrt(12)
    12 = 4 × 3
    12 = 6 × 2

     可以看到,后两个乘积就是前面两个反过来,反转临界点就在 sqrt(n)。

    换句话说,如果在 [2,sqrt(n)] 这个区间之内没有发现可整除因子,就可以直接断定 n 是素数了,因为在区间 [sqrt(n),n] 也一定不会发现可整除因子。

    时间复杂度:O(n√n)

     1     public static int countPrimes2(int n) {
     2         int count = 0;
     3         for (int i = 2; i < n; i++) {
     4             if (isPrimes(i)) {
     5                 count++;
     6             }
     7         }
     8         return count;
     9     }
    10 
    11     public static boolean isPrimes(int i) {
    12         //j<i 优化 j*j<i
    13         for (int j = 2; j * j < i; j++) {
    14             if (i % j == 0) {
    15                 return false;
    16             }
    17         }
    18         return true;
    19     }

    方法3:

      基于方法2,我们可以思考,一开始2为质数,那么2*i(2*i<n)的所有数是不是都不是质数了,因为能被2整除,i为3,是质数,那么3*i的所有数也都不是质数了,那么4刚已经被2标记不是质数了,依此类推...,该算法由希腊数学家厄拉多塞( m EratosthenesEratosthenes)提出,称为厄拉多塞筛法,简称埃氏筛。

    时间复杂度:O(nloglog n)

     1     public static int countPrimes(int n) {
     2         //所有数值的状态为1,假设所有数都为质数
     3         int[] isPrime = new int[n];
     4         Arrays.fill(isPrime, 1);
     5         int ans = 0;
     6         for (int i = 2; i < n; ++i) {
     7             //当isPrime[i]为1时说明,小于i的数都不能将i除尽,所以计数+1
     8             if (isPrime[i] == 1) {
     9                 ans += 1;
    10                 if ((long) i * i < n) {
    11                     //这里从i*i开始,因为 2*i,3*i,… 这些数一定在 i 之前就被其他数的倍数标记过了,和方法2的思想是一样的,j+=i,倍数增长嘛
    12                     for (int j = i * i; j < n; j += i) {
    13                         isPrime[j] = 0;
    14                     }
    15                 }
    16             }
    17         }
    18         return ans;
    19     }

     方法4:

      

     1     public static int countPrimes1(int n) {
     2         boolean[] isPrimes = new boolean[n];
     3         List<Integer> primes = new ArrayList<>(n);
     4         Arrays.fill(isPrimes, true);
     5 
     6         for (int i = 2; i < n; i++) {
     7             if (isPrimes[i]) {
     8                 primes.add(i);
     9             }
    10             for (int j = 0; j < primes.size() && i * primes.get(j) < n; j++) {
    11                 isPrimes[i * primes.get(j)] = false;
    12                 if (i % primes.get(j) == 0) {
    13                     break;
    14                 }
    15             }
    16         }
    17 
    18         return primes.size();
    19     }
  • 相关阅读:
    事务传播机制,搞懂。
    洛谷 P1553 数字反转(升级版) 题解
    洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here 题解
    洛谷 P1055 ISBN号码 题解
    洛谷 P2141 珠心算测验 题解
    洛谷 P1047 校门外的树 题解
    洛谷 P1980 计数问题 题解
    洛谷 P1008 三连击 题解
    HDU 1013 题解
    HDU 1012 题解
  • 原文地址:https://www.cnblogs.com/EmilZs/p/14078737.html
Copyright © 2011-2022 走看看