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     }
  • 相关阅读:
    Redis数据类型有哪些?
    什么情况下调用doGet()和doPost()?
    .JSP中动态include和静态include的区别?
    .Request对象的主要方法有哪些?
    Redis数据类型有哪些?
    Redis的特点什么是?
    请写出常用的linux指令
    接口绑定有几种实现方式,分别是怎么实现的?
    什么是 MyBatis 的接口绑定,有什么好处?
    MyBatis 的好处是什么?
  • 原文地址:https://www.cnblogs.com/EmilZs/p/14078737.html
Copyright © 2011-2022 走看看