携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
题目(Count Primes)
链接:https://leetcode-cn.com/problems/count-primes
解决数:957
通过率:37.6%
标签:数组 数学 枚举 数论
相关公司:microsoft amazon apple
给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。
示例 1:
输入: n = 10
输出: 4
解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:
输入: n = 0
输出: 0
示例 3:
输入: n = 1
输出:0
提示:
0 <= n <= 5 * 106
思路
- 质数的倍数都不是质数,从
2到n,假定所有数都是质数。- 先标记
2的倍数(从2 * 2开始),然后3的倍数(2 * 3标记过,从3 * 3开始)4是2的倍数(不是质数)- 继续标记
5(2 * 5标记过,3 * 5标记过,从5 * 5开始)- ...
- 直到 根号
n(从 根号n* 根号n开始,再往后 大于n了)
- 直到 根号
- ...
- 继续标记
- 先标记
- 从
2到n,根据标记结果h判断是质数,结果+1
代码
var countPrimes = function(n) {
var h = Array(n).fill(true), r = 0
for(var i = 2; i * i < n; i++) if(h[i]) for(var j = i * i; j < n; j += i) h[j] = false
for(var i = n; i-- > 2;) if(h[i]) r++
return r
};
- signs是用来记录“已经找过的数的倍数”的。
在里面的j循环中,一个个把找过数的倍数,对应的sign,设置为true。这样外循环就不会进入if循环,也就不会计数了。
- 外面的i循环是用来计数的,只要signs的数是false,就是质数,count就++
由于js里面判断!signs[i],啥都没有也是false,因此就不用像题解那样规定好数组一共有几个位置了。
js的优化
经过@Aaron大佬的提点,signs的时候规定好数组的大小,能减少内存的使用
我猜js和go一样,超过了规定的容量,就会把多增加的容量翻倍,倒不如事先规定好要用多少
var countPrimes = function (n) {
...
signs = new Array(n + 1)
...
};
试试用go
go
func countPrimes(n int) int {
count := 0
signs := make([]bool, n)
for i := 2; i < n; i++ {
if signs[i] {
continue
}
count++
for j := 2 * i; j < n; j += i {
signs[j] = true
}
}
return count
}
go就不能这么偷懒了,必须说明新建的这个切片是什么类型,有多少个位置。
go的bool,默认为false。因此如果是true就能直接拿来判断。