不断优化的素数算法

前言:素数判断是算法中重要的一环,掌握优秀的素数判断方法是算法player的必修课。本文介绍的是由简到繁的素数算法,便于初学者从入门到精通。


素数(质数):只能被 1 和它本身整除的数称作素数,如:2、3、5、7、11等

目录

  • 一、🍓 暴力算法 🍓
  • 二、🍉 埃氏筛法 🍉
  • 三、🍈 欧拉筛法 🍈

一、🍓 暴力算法 🍓

  暴力算法是利用循环,看 2 − n 2 -n 2n 之间是否有能被 n n n 整除的数,若有,则 n n n 就是素数,否则就不是。
  Java代码如下: 时间复杂度为 O ( n ) O(n) O(n)

	/*** 不停地判断 2 ~ n-1 之间是否有数可以被 n 整除* @param n 输入的数字* @return 返回true为素数,false不为素数*/public static boolean isPrime(int n){for (int i= 2; i < n; i ++){//只要有数能被 n 整除,就返回falseif(n % i == 0)return false;}//没有数能被 n 整除就返回truereturn true;}

简单优化:
  其实循环的范围可以缩小到 n 的平方根,这是数学定理,就不过多赘述,这样时间复杂度就减小到了 O ( n ) O(\sqrt{n}) O(n ) ,那么代码就改变为如下:

	/*** 不停地判断 2 ~ 根号 n 之间是否有数可以被 n 整除* @param n 输入的数字* @return 返回true为素数,false不为素数*/public static boolean isPrime(int n){//Math.sqrt()的作用是求平方根for (int i= 2; i <= Math.sqrt(n); i ++){//只要有数能被 n 整除,就返回falseif(n % i == 0)return false;}//没有数能被n整除就返回truereturn true;}

小结: 暴力算法只适合单个或少量的素数判断,若判断某个范围之间有哪些素数,时间复杂度可能会达到 O ( n n ) O(n \sqrt{n} ) O(nn ) ,如下代码就会达到。

	//求 n 以内的所有素数for (int i = 2; i <= n; i++){if(isPrime(i))System.out.println(i);}

另外还有简单优化的方法,如:跳过偶数(2除外)的判断等就不再讲述

二、🍉 埃氏筛法 🍉

  埃氏筛法是求 n 以内所有素数的方法,把不大于根号 n 的所有素数的倍数剔除,剩下的就是素数。方法及例子如下:

求 20 以内的所有素数:

  1. 列出 2 以后的所有序列:
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  2. 标记数列的第一个数为素数:
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  3. 划掉被标记的数的所有倍数:
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    2 3 5 7 9 11 13 15 17 19
  4. 标记剩下数列中当前标记的下一个数为素数,再次重复执行以上操作,最后标记的数应为 n \sqrt{n} n (向下取整):
    2 3 5 7 9 11 13 15 17 19   标记 3
    2 3 5 7 9 11 13 15 17 19   删除 3 的倍数
    2 3 5 7 11 13 17 19      得到新的数列
    2 3 5 7 11 13 17 19      下一个数 5 大于了 n \sqrt{n} n ,就不用再标记了,当前数列已是结果
  5. 最后剩下的数都是 n 以内的素数:
    2 3 5 7 11 13 17 19

说明:在暴力算法那里我们提到,判断素数只需要判断到是否能被 n \sqrt{n} n 整除即可,所以在埃氏算法中,我们只需要标记到 n \sqrt{n} n ,就能把所有非素数剔除

图解:我们可以借助一个 int 型数组,当前单元的值为 1 表示当前下标的数是素数,否则不是素数,我们是借助 0 来完成上面第三步的划掉倍数的操作。上面的例子最终得到的数组如下:
在这里插入图片描述

该图就表示:2 3 5 7 11 13 17 19 都是素数,其他都不是。虽然 0 和 1 下标上的元素也是 1,但我们可以控制下标从 2 开始,毕竟 2 是第一个素数

Java代码实现:

	/*** 埃氏筛法* @param n 要求的是 n 以内的素数* @return 返回 int 型数组,0 表示当前下标数字不是素数,1 则就是素数*/public static int[] sieve(int n){int[] arr = new int[n+1];// +1是为了让下标范围是 0 ~ n//让数组元素都为 1,即初始都为素数for (int i = 0; i <= n; i++)arr[i] = 1;//从 2 开始,若为素数就标记,并标记它的倍数不是素数for (int i = 2;i <= Math.sqrt(n); i++){//只需要标记到根号 n 即可if (arr[i] == 1){//素数才标记,因为当前位置可能是被标记的 0//j += i 控制 i 的倍数都被标记 0for (int j = 2 * i;j <= n;j += i){arr[j] = 0;}}}return arr;}

小结:埃氏筛法的时间复杂度为 O ( n ∗ l o g n ) O(n*log n) O(nlogn),相对于暴力算法有了优化,适用于 10 6 以内范围的数据处理。常见的应用有:n 以内范围的素数求总和区间内的素数

三、🍈 欧拉筛法 🍈

  欧拉筛法是埃氏筛法的升级版。在埃氏筛法中,很多数都会被标记多次不是素数,例如 10 会在标记素数 2 、5 的时候都被标记不是素数,欧拉筛法则让每个数只被标记一次不是素数。使自身的时间复杂度达到线性的 O ( n ) O(n) O(n)。算法及例子如下,具体概念及证明就不在本文阐述,有兴趣的小伙伴可以去搜一下:

求 20 以内的所有素数:红色表示素数蓝色表示不是素数

  1. 列出 2 以后的所有序列,初始都标记为素数:
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  2. 依次判断数列的每一个数,若为素数,则将其存放在一个数组中:
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  3. 依次标记当前数的所有已找到素数倍的数不是素数:(当前所有已找到素数只有 2,当前数为 2,那么标记 2 * 2 = 4 不是素数)
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  4. 标记一次,就判断当前数是否是当前素数的倍数,是则停止标记非素数,进入到下一个数的判断(这是使每个数只被标记一次的关键)
  5. 重复以上操作,直到判断到最后一个数(20):
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  当前数为 3,是素数,先加入素数数组,当前素数有 2,3,则标记 6 和 9 不是素数
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  当前数为 4,不是素数,不加入数组,当前素数有 2,3,则标记 8 不是素数,因为4是2的倍数,就结束标记(否则会重复标记12),对应第4步,进入下一个数
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  当前数为 5,是素数,先加入数组,当前素数有 2,3,5,则标记 10 15 不是素数(25大于20,不用标记)
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  当前数为 6,不是素数,不加入数组,当前素数有 2,3,5,则标记 12 不是素数,因为 12 是 2 的倍数,就结束标记(可以看到前面阻止了对 12 的标记,避免和这里发生重复),进入下一个数
    后续操作与同理,最后会发现每个数只被标记了一次。最终的数如下:
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

说明:通过以上步骤可以得出,需要两个数组,一个存已找到的素数,一个标记各个数是否为素数的数组

Java代码实现:

	/*** 欧拉筛法求 n 以内的所有素数* @param isPrime 标记是否为素数的数组,1表示是素数,0则不是* @param prime 存放以求得的素数的数组* @param n 就是 n 本身* @return 返回一共有几个素数*/public static int euler(int[] isPrime,int[] prime,int n){int cnt = 0;    //记录素数个数//让所有数组元素都为 1,即初始都为素数for (int i = 0;i <= n;i++)isPrime[i] = 1;//从 2 开始,若为素数就标记,并标记当前数的所有已找到素数倍的数不是素数for (int i = 2; i <= n; i++){//当前数为素数,则加入素数数组,并使 cnt计数加一if (isPrime[i] == 1) prime[++cnt] = i;//标记当前数的所有已找到素数倍的数不是素数for (int j = 1;j <= cnt && i * prime[j] <= n; j++){int k = i * prime[j];isPrime[k] = 0;//判断当前数是否是当前素数的倍数,是则停止标记非素数,进入到下一个数的判断//这里是使复杂度降低在线性的关键if (i % prime[j] == 0) break;}}return cnt;}

小结:欧拉筛将复杂度降低到线性,较于其他两种算法有了非常大的提升,但是远不及埃氏筛法容易理解,需要细细品味。但是算法嘛,很多时候都是先背板子,再刷题理解去掌握的,多用就好了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/149637.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

overleaf在线编辑工具使用教程

文章目录 1 用 orcid注册overleaf获取模板2 使用模板 1 用 orcid注册overleaf获取模板 通常来说&#xff0c;在期刊投稿网站information for author中找template 。下载压缩包后上传到over leaf中。 加入找不到官方模板&#xff0c;用overleaf中的 2 使用模板 .bib文件&…

需求变化频繁的情况下,如何实施自动化测试

一.通常来说&#xff0c;具备以下3个主要条件才能开展自动化测试工作: 1.需求变动不频繁 自动化测试脚本变化的频率决定了自动化测试的维护成本。如果需求变动过于频繁&#xff0c;那么测试人员就需要根据变动的需求来不断地更新自动化测试用例&#xff0c;从而适应新的功能。…

【Blender实景合成】会跳舞的神里绫华

效果预览 本文将介绍Blender用于实景合成的工作流程。 先看效果&#xff1a; 神里绫华爬上了我的办公桌 模型和动作资源准备 角色模型 本次主要使用的是原神游戏中&#xff0c;神里绫华的角色模型&#xff0c;该模型米哈游在模之屋网站上进行开源。 下载地址&#xff1a;ht…

react项目从webpack迁移到vite的解决方案

虽然webpack是前端工程编译工具的王者&#xff0c;但是最近vite牛逼吹的震天响&#xff0c;说什么开发/生产打包速度甩webpack 100条街。不管是不是事实&#xff0c;总得尝试一下吧。 于是说干就干&#xff0c;在网上找了很多资料&#xff0c;终于搞定了&#xff0c;以下就是r…

spark on hive

需要提前搭建好hive&#xff0c;并对hive进行配置。 1、将hive的配置文件添加到spark的目录下 cp $HIVE_HOME/conf/hive-site.xml $SPARK_HOME/conf2、开启hive的hivemetastore服务 提前创建好启动日志存放路径 mkdir $HIVE_HOME/logStart nohup /usr/local/lib/apache-hi…

【AI视野·今日CV 计算机视觉论文速览 第262期】Fri, 6 Oct 2023

AI视野今日CS.CV 计算机视觉论文速览 Fri, 6 Oct 2023 Totally 73 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Improved Baselines with Visual Instruction Tuning Authors Haotian Liu, Chunyuan Li, Yuheng Li, Yong Jae Lee大型多模…

多普勒频率相关内容介绍

图1 多普勒效应 1、径向速度 径向速度是作用于雷达或远离雷达的速度的一部分。 图2 不同的速度 2、喷气发动机调制 JEM是涡轮机的压缩机叶片的旋转的多普勒频率。 3、多普勒困境 最大无模糊范围需要尽可能低的PRF&#xff1b; 最大无模糊速度需要尽可能高的PRF&#xff1b…

Labview 实战 99乘法表

基于新手小白&#xff0c;使用Labview实现99乘法表&#xff0c;敢于发表自己的一点方法&#xff0c;还请各位大侠放过&#xff01; 如下&#xff1a; 运行效果如下&#xff1a; 思路为&#xff1a;将要显示出来的数据&#xff0c;全部转换为字符串形式&#xff0c;再塞入到数组…

Suricata + Wireshark离线流量日志分析

Suricata 环境搭建&#xff1a;基于Ubuntu坏境下的Suricata坏境搭建_奈何&#xff20;_&#xff20;的博客-CSDN博客 suricata&#xff1a;监控日志 wireshark:监控流量 同时使用需要降噪&#xff0c;因为规则有许多重叠 题目及要求我打包上传了&#xff0c;有需要的同学自…

Vmware 静态网络配置

概述 仅主机模式&#xff08;VMware1&#xff09;&#xff1a;使用host-only的方式是不能和外界通信的&#xff0c;只能够和本机的物理网卡通信 桥接&#xff08;VMnet0&#xff09;&#xff1a;使用桥接的方式使得自己的虚拟机和自己的真实机网卡在同一个网段 NAT&#xff0…

Tensorflow2 GPU 安装方法

一、Tensorflow2 GPU 安装方法 1. 首先安装Anaconda3环境2. 在Anaconda Prompt 中安装tensorflow23. 验证GPU是否可以使用4. 错误解决 1. 首先安装Anaconda3环境 https://www.anaconda.com/ 2. 在Anaconda Prompt 中安装tensorflow2 conda update conda conda create -n ten…

【Linux学习】05-2Linux上部署项目

Linux&#xff08;B站黑马&#xff09;学习笔记 01Linux初识与安装 02Linux基础命令 03Linux用户和权限 04Linux实用操作 05-1Linux上安装部署各类软件 05-2Linux上部署项目 文章目录 Linux&#xff08;B站黑马&#xff09;学习笔记前言05-2Linux上部署项目部署Springboot项目…

【SpringBoot】多环境配置和启动

环境分类&#xff0c;可以分为 本地环境、测试环境、生产环境等&#xff0c;通过对不同环境配置内容&#xff0c;来实现对不同环境做不同的事情。 SpringBoot 项目&#xff0c;通过 application-xxx.yml 添加不同的后缀来区分配置文件&#xff0c;启动时候通过后缀启动即可。 …

JavaScript系列从入门到精通系列第十五篇:JavaScript中函数的实参介绍返回值介绍以及函数的立即执行

文章目录 一&#xff1a;函数的参数 1&#xff1a;形参如何定义 2&#xff1a;形参的使用规则 二&#xff1a;函数的返回值 1&#xff1a;函数返回值如何定义 2&#xff1a;函数返回值种类 三&#xff1a;实参的任意性 1&#xff1a;方法可以作为实参 2&#xff1a;将匿…

OpenCV C++ Look Up Table(查找表)

OpenCV C Look Up Table&#xff08;查找表&#xff09; 引言 在图像处理和计算机视觉中&#xff0c;查找表&#xff08;Look Up Table, LUT&#xff09;是一种非常高效和实用的方法&#xff0c;用于快速地映射或更改图像的颜色和像素值。LUT 能够极大地提高图像处理算法的执…

【AI视野·今日Robot 机器人论文速览 第四十九期】Fri, 6 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Fri, 6 Oct 2023 Totally 29 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;ContactGen, 基于生成模型的抓取手势生成&#xff0c;类人五指手。(from 伊利诺伊大学 香槟) 数据集&#xff1a;GRAB da…

五种雷达波束模式简介及其应用场景

图1 雷达天线方向图一览 一、铅笔光束——Pencil beam: 方位角和仰角都很窄的光束&#xff08;像铅笔一样细&#xff09;&#xff1b;用于三维雷达&#xff0c;如仪表雷达、天气雷达和防空雷达。 二、扇形波束——Fan beam 方位角非常窄&#xff08;接近1至2&#xff09;&am…

【AI视野·今日NLP 自然语言处理论文速览 四十九期】Fri, 6 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Fri, 6 Oct 2023 Totally 44 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers MathCoder: Seamless Code Integration in LLMs for Enhanced Mathematical Reasoning Authors Ke Wang, Houxi…

socket.error: [Errno 10049]错误

今天在pycharm运行rl_server_no_training.py欲启动服务器时&#xff0c;却出现如下错误 Traceback (most recent call last):File "xxx/rl_server_no_training.py", line 333, in <module>main()File "xxx/rl_server_no_training.py", line 326, in…

Cocos Creator3.8 项目实战(六)Combobox控件的实现和使用

在cocoscreator 中&#xff0c;没有Combobox控件&#xff0c;无奈之下只能自己动手写一个。 ⚠️ 文末附 ComboBox.ts 、ComboBoxItem.ts 完整源码&#xff0c; 可直接拿去使用。 实现原理&#xff1a; 1、Combobox 背景图background 是一个sprite 控件&#xff0c;上面放了一…