前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang 刷leetcode 数学基础(1)素(质)数

golang 刷leetcode 数学基础(1)素(质)数

作者头像
golangLeetcode
发布2022-08-02 16:47:56
2640
发布2022-08-02 16:47:56
举报
文章被收录于专栏:golang算法架构leetcode技术php

求1——n的素数的个数,有以下三种方法:

1,遍历法:

对于k(1<k<=n);判断k 是否可以被 2到sqrt(k)的整数整除

代码语言:javascript
复制
func isprime(x int) bool{
    if x<=1{
        return false
        }
    for(i:=2;i<=sqrt(x+0.5);i++){//+0.5是为了防止精度误差
        if x%i==0{   
        return false
        }
     }
    return true
 }

此方法的问题在于许多不必要的计算,因此可以想到用空间换时间:筛选出来的素数的倍数都可以标记为合数

2,埃氏筛法

代码语言:javascript
复制
func init(){
prime:=make(map[int]bool) //prime[i]为flase表示i为质数
//初始化,默认都是
for(i:=2;i<maxn;i++){
        if !prime[i]{
            for j:=2*i;j<maxn;j+=i){//把所有i的倍数都进行标记
                        prime[j]=true;
            }
    }
  }
}

欧拉筛法优化的一点就是改进了埃氏筛法的一点冗余:可以发现,在埃氏筛法中,我们对每一个n都标记了不止一次。比如10,当i=2时,10作为2的倍数被标记一次,当i=5时,10依然是5的倍数,又被多余的标记一次。

3,欧拉筛选法

欧拉筛法思想:

其基础是 “任何一个合数都可以由两个质数相乘得到” 。那么对于每一个n我们都可以用比它小的某一个质数来标记。

代码语言:javascript
复制
func prime(n int)int{
    m:=make([]int,n)
    p:=make([]int,n)
    count:=0
    for i:=2;i<=n;i++{
        if m[i-1]==0{  // 如果未被筛过,则为素数
            p[count]=i
            count++
        }
        for j:=0;j<count;j++{
            if i*p[j]>n{
                break
            }
            m[i * p[j]-1] = 1;     // 将已经记录的素数的倍数进行标记
            if i % p[j] == 0{     //关键步骤
        break
            }
        }
    }
    fmt.Println(count)
    return count
}

欧拉筛的难点就在于对if (i % prime[j] == 0)这步的理解,当i是prime[j]的整数倍时,记 m = i / prime[j],那么 i * prime[j+1] 就可以变为 (m * prime[j+1]) * prime[j],这说明 i * prime[j+1] 是 prime[j] 的整数倍,不需要再进行标记(在之后会被 prime[j] * 某个数 标记),对于 prime[j+2] 及之后的素数同理,直接跳出循环,这样就保证了每个合数都是被它的最小因子筛去的,避免了重复标记。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档