计算小于非负整数n的质数数量

Example:

Input: 10 Output: 4 Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.

1:算法思想参考

这个算法的过程如下图所示,我们从2开始遍历到根号n,先找到第一个质数2,然后将其所有的倍数全部标记出来,然后到下一个质数3,标记其所有倍数,一次类推,直到根号n,此时数组中未被标记的数字就是质数

下面的方法会超过时间限制 ,因为在数组中查找某个数值是否存在("not in")需要消耗大量时间

def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<2:
            return 0
        numList = []
        sum = 0
        for i in range(2,int(math.sqrt(n))+1):
            count = i
            while i*count<n:
                if i*count not in numList:
                    numList.append(i*count)
                count += 1
        for i in range(2, n):
            if i not in numList:
                sum += 1
        return sum

下面的方法是可行的,但是会花费过多的时间,因为代码中不是用小于根号n的质数来做标记,而是用小于根号n的所有数字来做标记,这样会导致大量的数字被重复标记

def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<2:
            return 0
        numList = [True for i in range(n)]
        sum = 0
        for i in range(2,int(math.sqrt(n))+1):
            count = i
            while i*count<n:
                numList[i*count]=False
                count += 1
        for i in range(2, n):
            if numList[i] is True:
                sum += 1
        return sum

和上面等价

def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<2:
            return 0
        numList = [True for i in range(n)]    #一次性赋值True
        for i in range(2,int(math.sqrt(n))+1):
            count = i
            while i*count<n:
                numList[i*count]=False
                count += 1
        return numList.count(True)-2 #去除0和1

下面的方法保证了只对小于根号n的质数进行操作,但这种方法还是会标记很多重复的数字

def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<2:
            return 0
        numList = [True for i in range(n)]
        for i in range(2,int(math.sqrt(n))+1):
             if numList[i] is True:    #过滤是否为小于根号n的质数
                count = i
                while i*count<n:
                    numList[i*count]=False
                    count += 1
        return numList.count(True)-2

下面这种方法和上面的方法其实一样,但是时间消耗大大缩短了

def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<2:
            return 0
        numList = [True]*n
        for i in range(2,int(math.sqrt(n))+1):
             if numList[i] is True:    #过滤是否为小于根号n的质数
                numList[i*i:n:i] = [False]*len(range(i*i,n,i))
        return numList.count(True)-2

算法题来自:https://leetcode-cn.com/problems/count-primes/description/