文章简介
本文记录寻找素数的几种算法, 本文中的O()没有指明默认表示时间复杂度
代码使用Java
目录
正文
素数/质数, 一个只可以被1和它本身整除的数, 换句话说, 不能被比他小的任意两个整数的乘积表示的数字.
打印1~n之间素数, 一直是一个入门级别的算法, 在学习编程思想的时候会出现在各种题里,
文中n取100, 打印结果都为:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
我们最开始写的可能是这样的
穷举计数法(判断O(n))
/**
* 打印1到n间的所有素数, 包括n.
*
* @param n 查找到n
*/
static void printPrimeNumber(int n) {
for (int i = 1; i < n + 1; i++) {
/*这个循环遍历1~n的所有数字i*/
/*一个被整除次数的标志位, 如果为2, 只被1和它本身整除了, 是素数, 其它>2的值就证明不是素数*/
int divided = 0;
for (int j = i; j >= 1; j--) {
/*这个循环遍历1~i的所有数字, 如果能被整除, "能被整除"计数器+1 */
if (i % j == 0) {
divided++;
}
}
if (divided == 2) {
/*如上所述, 该数是素数*/
System.out.print(i + " ");
}
}
}
n=1000时,一百次平均用时10.76ms
优化: 布尔+break(判断 小于O(n))
/**
* 打印1到n间的所有素数, 包括n.
*
* @param n 查找到n
*/
static void printPrimeNumberPro(int n) {
/*for (int i = 1; i < n+1; i++) {*/
/* 1不是素数, 可以直接跳过*/
for (int i = 2; i < n + 1; i++) {
/*int divided = 0;*/
/*本质上, 判定一个数字是不是素数, 只需要看能不能被n与1以外的数字整除就行了, 利用一个bool量, 再加上break, 不要傻傻计数*/
boolean isPrime = true;
/*for (int j = i - 1; j > 1; j--) {*/
/*直觉上, 从小向大而不是从小向大遍历除数, 可以更快判定, 后面给出这点的证明*/
for (int j = 2; j < i; j++) {
if (i % j == 0) {
/*divided++*/
isPrime = false;
/*break可以减少比较次数*/
break;
}
}
if (isPrime) {
System.out.print(i + " ");
}
}
}
n=1000时,一百次平均用时6.23ms
优化: 利用数学推导缩小除数范围(判断O( n \sqrt{n} n))
一个数字n可以被整除时, 意味着它可以被 除数和商的乘积表示, 设除数为j, 商为k
若 : n j = k 若: \frac{n}{j}=k\\ 若:jn=k
此时
n = n ∗ n = j ∗ k 又 : j ≠ k \begin{aligned} n &= \sqrt{n}*\sqrt{n} \\

本文详细介绍了多种寻找素数的算法,包括穷举法、优化后的布尔+break法、利用数学推导缩小除数范围的方法、埃氏筛选法及其优化、以及欧氏筛法等。每种方法均给出了具体的实现代码及时间复杂度分析。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



