力扣精解

初级算法-数学-计数质数

2021-09-26  本文已影响0人  coenen

统计所有小于非负整数 n 的质数的数量。
名次解释:
质数:质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的自然数.

提示:
0 <= n <= 5 * 106

摘一个示例做个说明.
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
条件分析:
  1. 统计所有小于n的质数的个数 -> 是要进行计数
  2. 非负整数 n -> n为0或者正整数,可能为0或1.0或1都不是质数
  3. 0 <= n <= 5 * 106 -> 老老实实计算吧,不要想着map解决问题
解决思路1:
  1. 根据分析1,采用累计计算,因为是统计一个n内所有的,也就是每个小于n的都要计算,所以采用循环
  2. 根据分析2,对0或1做特殊处理,直接返回比较快.
  3. 需要判断n以内的每个数是不是质数
因为是小于n的统计,所以当n小于3时,直接0、1、2的时候可以直接返回0.然后判断每一个是否是质数.累计相加即可,但是结果也是显而易见的.值太大的时候,直接超时了.
func countPrimes(_ n: Int) -> Int {
    var count = 0
    if n == 0 || n == 1 || n == 2{
        return count
    }
    for i in 2 ..< n {
        count += isPrimes(i)
    }
    
    return count
}

func isPrimes(_ n: Int) -> Int {
    
    for i in 2 ..< n {
        if n % i == 0 {
            return 0
        }
    }
    
    return 1
}
解决思路2:分析同思路1

1.优化点,从头开始判断的时候,如果不是质数,则相应的它的倍数也不会是质数.相应的倍数的倍数,直到大于n前都不会是质数.

定义一个长度为n的临时存储数据.然后循环判断小于n的数.如果存储的该数是质数则将该数字进行翻倍处理.直到结束.最后循环临时变量即可.
func countPrimes(_ n: Int) -> Int {
    if n < 3 {
        return 0
    }
    var count: Int = 0
    var isPrimes = [Bool](repeating: true, count: n)
    for index in 2 ..< n {
        if isPrimes[index] {
            var i = 2*index
            while i < n {
                isPrimes[i] = false
                i += index
            }
        }
    }
    for index in 2 ..< n {
        if isPrimes[index] {
            count += 1
        }
    }
    
    return count
}

测试用例:

let n = 0
let n = 1
let n = 2
let n = 3
let n = 10
let n = 100000
let n = 900000

考察要点:

上一篇下一篇

猜你喜欢

热点阅读