LeetCode计数质数Swift

统计所有小于非负整数 n 的质数的数量。

示例 1:

输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7


示例 2:

输入:n = 0
输出:0


示例 3:

输入:n = 1
输出:0

提示:

0 <= n <= 5 * 106

思路一:质数,只能被1和本身整除。

    //求n以内的质数
    func countPrimes1(_ n: Int) -> Int {
        if n < 3 {
            return 0
        }
        if n == 3 {
            return 1
        }
        var array:[Int] = [2]
        for i in 3 ... n - 1 {
            //默认是质数
            var flag = true
            for j in 2 ... i - 1 {
                if i % j == 0 {
                    //能整除就是合数
                    flag = false
                    break
                }
            }
            if flag == true {
                array.append(i)
            }
        }
        print(array)
        return array.count
    }

优化一:大于2的偶数肯定是合数,先过滤掉。然后除以2到i的平方根即可。

   //求n以内的质数
    func countPrimes4(_ n: Int) -> Int {
        if n < 3 {
            return 0
        }
        if n == 3 {
            return 1
        }
        if n == 4 || n == 5 {
            return 2
        }
        
        var array:[Int] = [2,3]
        for i in 5 ... n - 1 {
            if i % 2 == 0 {
                //偶数肯定是合数
                continue
            }
            //默认是质数
            var flag = true
            //如果一个合数,那它除了1和他本身一定还有别的约数,假如这个数是num,num=m*n 一定可以分解为两个整数相乘,设一个命题 ,num可以分解为两个数相乘且这两个数都大于num在平方根,m>sqrt(num) n>sqrt(num) 根据数学知识可以知道m*n>num 这与命题相反,所以命题是假的。所以合数一定至少有一个不大于sqrt(num)约数,只要找到这个数就可以了。
            let value = Int(sqrt(Double(i)))
            for j in 2 ... value {
                if j % 2 == 0 {
                    //偶数肯定是合数
                    continue
                }
                if i % j == 0 {
                    //能整除就是合数
                    flag = false
                    break
                }
            }
            if flag == true {
                array.append(i)
            }
        }
        return array.count
    }

思路二:性能很高

1. 厄拉多塞筛法
西元前250年,希腊数学家厄拉多塞(Eeatosthese)想到了一个非常美妙的质数筛法,减少了逐一检查每个数的的步骤,可以比较简单的从一大堆数字之中,筛选出质数来,这方法被称作厄拉多塞筛法(Sieve of Eeatosthese)。

具体操作:先将 2~n 的各个数放入表中,然后在2的上面画一个圆圈,划去2的其他倍数;第一个既未画圈又没有被划去的数是3,将它画圈,划去3的其他倍数;现在既未画圈又没有被划去的第一个数 是 5,将它画圈,并划去5的其他倍数……依次类推,一直到所有小于或等于 n 的各数都画了圈或划去为止。这时,表中画了圈的以及未划去的那些数正好就是小于 n 的素数。

分析:整个过程就是不停的画圈,最后没有被圈住的就是我们要的质数

class Solution {
    func countPrimes(_ n: Int) -> Int {
        if n < 3 {
            return 0
        }
        var data = [Bool](repeating: true, count: n)
        var count = 0

        for i in 2..<n {
            if data[i] {
              var j = i*2
              while j<n {
                data[j] = false
                j+=i
              }
              count+=1
            }
        }
        return count
    }
}
原文地址:https://www.cnblogs.com/huangzs/p/14205614.html