简介


什么是素数?
   素数也叫质数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

判断素数的方法:
   思路一:判断一个数是否素数,只需要把m 被 2~m-1之间的每一个整数去除,如果都不能被整除,那么m就是一个素数。
   思路二:用n分别去除2到sqrt(n)-1,如果能被整除,则表明此数不是素数,反之是素数。

解法

暴力方式

通过双层循环判断查找、时间复杂度 O(n^2)


//暴力判断 时间复杂度O(n^2)
func TestIsPrime(t *testing.T) {
	count:=0
	for i:=2; i< num ;i++  {
		if is_prime(i){
			count++
		}
	}
	fmt.Printf("Prim_Count: %v ; prime: %v; \n",count,num)
}
//暴力判断
func is_prime(num int) bool {
	//从2遍历到n-1,看看是否有因子
	for i := 2; i < num; i++ {
		if num %i == 0 {
			//发现一个因子被整除
			return false
		}
	}
	return true
}

利用sqrt平方根方法求素数的个数

利用sqrt平方根方法求素数的个数,函数的时间复杂度降为 O(sqrt(N))

利用sqrt平方根方法求素数的个数,例如 num =12 能够发现
12 = 2 × 6
12 = 3 × 4
12 = sqrt(12) × sqrt(12)
12 = 4 × 3
12 = 6 × 2
可以看到,后两个乘积就是前面两个反过来,反转临界点就在 sqrt(n)。
也就是说,如果在 [2,sqrt(n)] 这个区间之内没有发现可整除因子,就可以直接断定 n 是素数了,因为在区间 [sqrt(n),n] 也一定不会发现可整除因子。

函数的时间复杂度降为 O(sqrt(N))

/*
	利用sqrt平方根方法求素数的个数,例如 num =12 能够发现
	12 = 2 × 6
	12 = 3 × 4
	12 = sqrt(12) × sqrt(12)
	12 = 4 × 3
	12 = 6 × 2
	可以看到,后两个乘积就是前面两个反过来,反转临界点就在 sqrt(n)。
	也就是说,如果在 [2,sqrt(n)] 这个区间之内没有发现可整除因子,就可以直接断定 n 是素数了,因为在区间 [sqrt(n),n] 也一定不会发现可整除因子。
	函数的时间复杂度降为 O(sqrt(N))
 */
func TestIsPrimeV2(t *testing.T) {
	fmt.Printf("nSqrt:%v \n",math.Sqrt(float64(num)))
	count:=0
	for i:=2; i< num; i++  {
		if is_prime_v2(i){
			//fmt.Printf("prime : %v \n",i)
			count++
		}
	}
	fmt.Printf("Prime_Count: %v ; prime: %v; \n",count,num)
}

//利用Sqrt 判断是否素数
func is_prime_v2(num int) bool {
	nSqrt :=int(math.Sqrt(float64(num)))
	//fmt.Printf("nSqrt:%v \n",nSqrt)
	//从2遍历到n的方根,看看是否有因子
	for i := 2; i<= nSqrt ; i++ {
		if num%i == 0 {
			return false
		}
	}
	return true
}

高效实现 求countPrimes

首先从2开始
我们知道 2 是一个素数,那么 2 × 2 = 4, 3 × 2 = 6, 4 × 2 = 8... 都不可能是素数了。
然后我们发现3也是素数,那么 3 × 2 = 6, 3 × 3 = 9, 3 × 4 = 12... 也都不可能是素数了

/*
高效实现 countPrimes
首先从2开始,我们知道 2 是一个素数,那么 2 × 2 = 4, 3 × 2 = 6, 4 × 2 = 8... 都不可能是素数了。
然后我们发现 3 也是素数,那么 3 × 2 = 6, 3 × 3 = 9, 3 × 4 = 12... 也都不可能是素数了。
*/
func TestIsPrimeV3(t *testing.T) {
	fmt.Printf("Prime_Count: %v ; prime: %v; \n",prime_count(num),num)
}
func prime_count(num int) int{
	bools := make([]bool,num)
	for i:=0; i<num ;i++ {
		bools[i]=true
	}
	for i:=2; i*i < num; i++{
		if bools[i] {
			for j:=i*i; j < num; j+=i {
				bools[j] = false
			}
		}
	}
	count:=0
	for  i:= 2; i < num; i++{
		if bools[i] {
			count++
		}
	}
	return count
}

代码可执行

package algorithmProject

import (
	"fmt"
	"math"
	"testing"
)
var num=1000000

/*
什么是素数?
	素数也叫质数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

判断素数的方法:
	思路一:判断一个数是否素数,只需要把m 被 2~m-1之间的每一个整数去除,如果都不能被整除,那么m就是一个素数。
	思路二:用n分别去除2到sqrt(n)-1,如果能被整除,则表明此数不是素数,反之是素数。
*/

//暴力判断 时间复杂度O(n^2)
func TestIsPrime(t *testing.T) {
	count:=0
	for i:=2; i< num ;i++  {
		if is_prime(i){
			count++
		}
	}
	fmt.Printf("Prim_Count: %v ; prime: %v; \n",count,num)
}
//暴力判断
func is_prime(num int) bool {
	//从2遍历到n-1,看看是否有因子
	for i := 2; i < num; i++ {
		if num %i == 0 {
			//发现一个因子被整除
			return false
		}
	}
	return true
}

/*
	利用sqrt平方根方法求素数的个数,例如 num =12 能够发现
	12 = 2 × 6
	12 = 3 × 4
	12 = sqrt(12) × sqrt(12)
	12 = 4 × 3
	12 = 6 × 2
	可以看到,后两个乘积就是前面两个反过来,反转临界点就在 sqrt(n)。
	也就是说,如果在 [2,sqrt(n)] 这个区间之内没有发现可整除因子,就可以直接断定 n 是素数了,因为在区间 [sqrt(n),n] 也一定不会发现可整除因子。
	函数的时间复杂度降为 O(sqrt(N))
 */
func TestIsPrimeV2(t *testing.T) {
	fmt.Printf("nSqrt:%v \n",math.Sqrt(float64(num)))
	count:=0
	for i:=2; i< num; i++  {
		if is_prime_v2(i){
			//fmt.Printf("prime : %v \n",i)
			count++
		}
	}
	fmt.Printf("Prime_Count: %v ; prime: %v; \n",count,num)
}

//利用Sqrt 判断是否素数
func is_prime_v2(num int) bool {
	nSqrt :=int(math.Sqrt(float64(num)))
	//fmt.Printf("nSqrt:%v \n",nSqrt)
	//从2遍历到n的方根,看看是否有因子
	for i := 2; i<= nSqrt ; i++ {
		if num%i == 0 {
			return false
		}
	}
	return true
}

/*
高效实现 countPrimes
首先从2开始,我们知道 2 是一个素数,那么 2 × 2 = 4, 3 × 2 = 6, 4 × 2 = 8... 都不可能是素数了。
然后我们发现 3 也是素数,那么 3 × 2 = 6, 3 × 3 = 9, 3 × 4 = 12... 也都不可能是素数了。
*/
func TestIsPrimeV3(t *testing.T) {
	fmt.Printf("Prime_Count: %v ; prime: %v; \n",prime_count(num),num)
}
func prime_count(num int) int{
	bools := make([]bool,num)
	for i:=0; i<num ;i++ {
		bools[i]=true
	}
	for i:=2; i*i < num; i++{
		if bools[i] {
			for j:=i*i; j < num; j+=i {
				bools[j] = false
			}
		}
	}
	count:=0
	for  i:= 2; i < num; i++{
		if bools[i] {
			count++
		}
	}
	return count
}

结果验证

Golang 实现求素数【 输入N,求N内素数个数 】_算法