三种素数筛总结——(朴素筛,埃氏筛,线性筛)

三种素数筛总结——(朴素筛,埃氏筛,线性筛)_第1张图片
但行好事,莫问前程。

题目背景

题目:(leetcode)204.计数质数


给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。

对于这类求解素数个数有关的题目,通常采用质数筛算法。

本文不计算时间复杂度,只介绍自己对于思路的理解。



质数筛

1. 朴素筛法

时间复杂度:

O(n√n)

思想:

对于每一个i∈[2,n],枚举 [2,i-1] 中是否存在 i 的因子,有=》合数,没有=》素数

又因为对于i而言,因子一定是小于√i的,故枚举可以从 [2,i-1] 优化为 [2,√i],因此复杂度为n√n。

代码





2. 埃氏筛法

时间复杂度:

O(n*log(logn))

思想:

在从小到大枚举素数的过程中,设置标志数组val,每找到一个素数便将其倍数全部筛除(因为素数的倍数一定是合数),在后续枚举过程中直接通过判断val跳过合数,剩下来的就是素数。

这里利用了算术基本定理,简而言之就是,所有的合数都可以分解成若干素数的幂的乘积,这里需要思考一下。最新枚举到的合数,其因子一定比其本身要小,那么该因子就一定在之前被枚举到过 <==> 即合数已经在之前被筛除了。

代码:

int IsPrime(int n){
	//计算小于n的素数个数
	int cnt = 0;//计数
	//bool val[5000010]={0};//val[i]表示i是否是素数,先假设全是素数
	bool *val = new bool[5000010]();//val[i]表示i是否是素数,先假设全是素数
	for(int i=2; i<n; i++)
	{
		//标志判断
		if(val[i])//判断i是否是合数
		{
			continue;
		}    
		cnt++;
		//开始筛除(核心算法)
		for(int j=i; j*i<=n; j++){		//开始筛除i的倍数
		//j=i而不是j=2是因为:前面的合数必被过往素数列举了
		//j<=n/i是因为:i*j<=n超出范围了,后者int*int易越界,int/int的形式更加保险。
			val[i*j]=1;
		}
	}
	return cnt;
}



3. 线性筛法

时间复杂度:

O(n)

思路:

线性筛是对于埃氏筛法的优化,举个例子介绍埃氏筛法的缺陷

对于2 3 6这三个数,如果用埃氏筛法,会发现在2筛除过程和3筛除过程中,6都被筛除了一遍,这也就是埃氏筛法的缺陷,会有重复筛除的情况,而线性筛则在用哪个素数进行筛除这个点上作了改进,线性筛采用了若干素数中最小的素数来筛除,基于基本算术定理,我们知道合数都只能被唯一的分解成若干素数的幂的积,因此每个合数只有唯一的最小素因数,这样在筛除过程中就不会发生重筛,因此最终复杂度就变成了O(n)。

代码解释:
具体代码实现较复杂,和埃氏算法不同点在于:
1、多了一个prime数组存储素数
2、从 埃氏筛法:用单个的素数进行筛除 变成 用枚举过程中的 i 对遍历过程中已找到的素数 prime[j] 进行倍乘( i*prime[j] )
3、对 i 进行最小素因子的考察。

代码:

int IsPrime(int n){
	int cnt = 0;//计数
	int prime[5000000];//按顺序依次存储素数
	//bool val[5000010]={0};//val[i]表示i是否是素数,先假设全是素数
	bool *val = new bool[5000010]();//val[i]表示i是否是素数,先假设全是素数
	for(int i=2; i<n; i++)
	{   
        //保存素数
		if(!val[i])//判断i是否是素数
		{
			prime[cnt++] = i;//保存第cnt+1个素数
		}    
        //开始筛除(算法核心)
		for(int j=0; prime[j]<=n/i && j<cnt; j++){		
			val[i*prime[j]] = 1;
            //判断是否prime[j]是否是i的素因数,如果是,则说明后面j++后,prime[j]就不再是i*prime[j]的最小素因数了
            //进行基本算术定理的分解,可以发现此时i*prime[j]=(prime[j-1]^k)*prime[j]
            //上式的最小素因数是prime[j-1],因此直接break该i,进入下一个i。
            if(i % prime[j] == 0)
                break;
		}
	}
	return cnt;
}

你可能感兴趣的:(算法,算法,leetcode,职场和发展)