简介
什么是素数?
素数也叫质数,是指在大于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
}