【算法零基础学习】关于素数的那些事儿

关于素数

素数,又称为质数。它是指那些只包含 1 和 它本身 两个因子的自然数。与之相对应的数称为 合数

特别的, 1既不是素数也不是合数
在这里插入图片描述

用程序判定一个数是否是素数

使用素数的定义

因为素数只有 1 和 它本身 两个因子,所以,我们可以遍历[2,n-1]中的每一个数,如果其中没有 n 的因子,那么就说明 n 是素数。代码如下:

public boolean isPrime(int n) {
        for (int i = 2; i < n; ++i) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

这种做法的时间复杂度为O(n)

优化一

我们可以对上面的方法进行优化。
根据素数的定义,我们可以知道,判断一个数是否为素数,最关键的一点在于这个数是否包含除去 1 和 它自身之外 的其他因子。我们的优化从它的因子特征入手:
我们先看两个例子: 6 ÷ 2 = 3 6\div2=3 6÷2=3 150 ÷ 3 = 50 150 \div 3=50 150÷3=50
我们发现:

  1. 对于任何一个正整数 n,如果它可以被 x 整除,那么就可以说明,它也可以被 n/x 整除。
  2. 并且,对于 x 和 n/x,一定有一个较小值。我们假设 x 是较小值,那么一定会存在 x ≤ n / x x \leq n /x xn/x。也就是说, x ≤ n x \leq \sqrt{n} xn

所以,我们不需要遍历[2,n-1]中的每一个数,只需要遍历在[2, n \sqrt{n} n ]中是否存在 n 的因子即可。优化后的代码如下:

public boolean isPrime(int n) {
		int s = (int)Math.sqrt(n);
        for (int i = 2; i <= s; ++i) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

这里,它的时间复杂度优化到了 O(sqrt(n))

推荐题目

题目
1492. n的第k个因子
1952. 三除数

筛选出 n 之内的所有素数

枚举法

这是最简单的方法,就是枚举[1,n]所有的数,判断是否是素数。

public List<Integer> selPrime(int n){
		List<Integer> list = new ArrayList<>();
		for(int i = 1; i <= n; ++i){
			if(isPrime(i))
				list.add(i);
		}
		return list;
}

boolean isPrime(int n){
	int s = (int)Math.sqrt(n);
	for(int i = 2; i <= s; ++i){
		if(n % i == 0)
			return false;
	}
	return true;
}

时间复杂度:O( n 3 2 n^{\frac{3}{2}} n23)

埃氏筛

枚举法虽然简单,但是它的性能却并不可观。所以,介绍另外一种方法——埃氏筛。简单介绍一下它:

埃氏筛,全称埃拉托斯特尼筛法,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。

📖核心思想

在遍历 [1, n] 的过程中,如果发现某个素数 p,那么它的 i 倍一定不是素数。
所以,我们可以使用一个 长度为 n 的数组标识素数。在发现某一个素数之后,将它的所有倍数标识为合数。

👨‍💻代码

// 0 代表素数,1 代表合数
public int  countPrimes(int n){
	if(n < 2)
		return 0;
	int cnt = 0;
	int[] primes = new int[n+1];
	primes[0] = primes[1] = 1;
	for(int i = 2; i <= n; ++i){
		if(primes[i] == 0){
			++cnt;
			for(int j = 2; ; ++j){
				if(j * i <= n)
					primes[j * i] = 1;
			}
		}
	}
}

推荐题目

题目
204. 计数质数
1175.质数排列
866. 回文素数
筛选N以内的素数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值