「前端刷题」204.计数质数(MEDIUM)

505 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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

思路

  • 质数的倍数都不是质数,从2n,假定所有数都是质数。
    • 先标记2的倍数(从2 * 2开始),然后3的倍数(2 * 3标记过,从3 * 3开始)
      • 42的倍数(不是质数)
        • 继续标记52 * 5标记过,3 * 5标记过,从5 * 5开始)
          • ...
            • 直到 根号n(从 根号n * 根号n 开始,再往后 大于n 了)
  • 2n,根据标记结果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就能直接拿来判断。