这道题看着挺简单,但是一写就超时了,想了一下,主要耗时在计算质数上,如果用枚举法去判断一个数是不是质数,肯定就会超时。
迭代一遍的写法应该是:
class Solution:
def countPrimes(self, n: int) -> int:
if n < 3:
return 0
else:
# 首先生成了一个全部为1的列表
output = [1] * n
# 因为0和1不是质数,所以列表的前两个位置赋值为0
output[0],output[1] = 0,0
# 此时从index = 2开始遍历,output[2]==1,即表明第一个质数为2,然后将2的倍数对应的索引
# 全部赋值为0. 此时output[3] == 1,即表明下一个质数为3,同样划去3的倍数.以此类推.
for i in range(2,int(n**0.5)+1):
if output[i] == 1:
output[i*i:n:i] = [0] * len(output[i*i:n:i])
# 最后output中的数字1表明该位置上的索引数为质数,然后求和即可.
return sum(output)
在上面遍历索引的时候用到了一个非常好的技巧.:即i是从(2,int(n**0.5)+1)而非(2,n).这个技巧是可以验证的,比如说求9以内的质数个数,那么只要划掉sqrt(9)以内的质数倍数,剩下的即全为质数.。所以在划去倍数的时候也是从i*i开始划掉,而不是i+i。
其中,output[i*i:n:i] = [0] * len(output[i*i:n:i])
这句话比较难理解。
解释:
测试代码:
a=[1,2,3,4,5,6,7,8,9,10,11,12]
a[1:9:2]=[0]*len(a[1:8:2]) # 1能取的到,9取不到
print(a)