leetcode——Count Primes

来源:互联网 发布:单点登录系统源码 编辑:程序博客网 时间:2024/06/05 19:56

题目

Description:

Count the number of prime numbers less than a non-negative number, n.

方法

对于这道题,最简单最直观的方法往往是:对n以下的每一个数字进行判断从而求出个数。而在对每个数字(比如x)判断的时候,又是暴力验证的思想,即从2开始一直到sqrt(x)进行相除判断是否整除。更有甚者直接从2到x/2或x进行判断。这样的效率是极其低下的,这篇文章如果讲的是以上的东西,那就失去意义了。下面来讲一个最为高效的做法,并不难,关键在于理解。

先来看图:
这里写图片描述

我们从一个有着n个数字的一维数组开始,先看第一个数字2.我们知道所有因数为2的数字(除了2本身)都不是质数,所以我们把他们标记为非质数;然后看下一个数字,3.同样道理,所有因数为3的数字也都不是质数,比如 3 × 2 = 6, 3 × 3 = 9, … ,这些一定不是质数,所以我们也可以把他们标记出来。现在来看4,这是一个已经标记出来的数字。这说明什么?难道还需要把所有因数有4的数字去掉吗?

4并不是质数,因为它能被2整除,这也告诉我们所有以4为因数的数字都能被2整除,而它们已经被剔除掉了(在讨论2的时候)。所以我们可以跳过4去考虑下一个数字:5。现在,所有因数为5的数字,比如5 × 2 = 10, 5 × 3 = 15, 5 × 4 = 20, 5 × 5 = 25, … 都能够被剔除掉了。不过这里有一个小的优化:我们并不需要从5x2开始,我们仅仅需要从5 x 5开始。原因如下:

5 × 2 = 10 早在讨论2的时候就已经被排除掉了,同理,5 x 3 早在讨论3的时候被排除掉了。因此,既然我们一路从2上来,那么任何比当前数字小的因数(当前为5)都已经做过排除处理,因此我们不需要再讨论它们;我们所要讨论的是从当前数字的平方开始一直到最末的这些数。如果当前数字为p,p2为pxp,那么我们要讨论的就是:p2,p2 + p, p2 + 2p, … 而这个循环的终止条件就是,j < n (其中,j = p2 + m*p).

当循环结束的时候,那些没被标记过的数字就是质数。

代码

public int countPrimes(int n) {        boolean[] isPrime = new boolean[n+1];        for(int i=1;i<=n;i++){            isPrime[i] = true;        }        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 count = 0;        for(int i=2;i<n;i++){            if(isPrime[i])                count++;        }        return count;    }
0 0
原创粉丝点击