【Android面试八股文】荣耀面试算法题:输出1到1000中间有多少个素数?

news2024/9/9 0:42:51

文章目录

  • 一、素数的定义
  • 二、如何判断为质数?
    • 2.1 试除法
      • 2.1.1 具体步骤
      • 2.1.2 算法实现
    • 2.2 埃拉托斯特尼筛法
      • 2.2.1 原理
      • 2.2.2 具体步骤
      • 2.2.3 算法实现
      • 2.2.4 示例
      • 2.2.5 优点
      • 2.2.6 缺点
  • 三、输出1到1000中间有多少个素数?
    • 3.1 试除法
    • 3.2 埃拉托斯特尼筛法
    • 3.3 两个算法比较

一、素数的定义

  • 素数又称质数。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。 换句话说,只有两个正因数(1和自己)的自然数即为素数。

  • 比1大但不是素数的数称为合数

  • 1和0既非素数也非合数。

二、如何判断为质数?

2.1 试除法

试除法是判断一个数是否是素数的基本方法。

它的基本思路是:

  • 对于一个大于1的整数 n,如果 n 不能被2 n \sqrt{n} n ​ 之间的任何整数整除,则 n 是素数。
  • 否则,n 不是素数。

2.1.1 具体步骤

  1. 特例处理:如果 n 小于等于1,则 n 不是素数。
  2. 处理2和3:2和3是素数,可以直接返回true。
  3. 排除偶数:如果 n 是偶数且大于2,则 n 不是素数。
  4. 试除:从5开始检查到 n \sqrt{n} n ​ ​ 的奇数,如果 n 能被其中任何一个数整除,则 n 不是素数。

2.1.2 算法实现

public class PrimeChecker {
    public static void main(String[] args) {
        int number = 29;
        boolean isPrime = isPrime(number);
        System.out.println(number + " 是素数吗? " + isPrime);
    }

    public static boolean isPrime(int number) {
    	// 首先处理一些特例。如果 number 小于等于1,则返回false。
        if (number <= 1) {
            return false;
        }
        // 如果 number 是2或3,则返回true,因为它们是素数。
        if (number == 2 || number == 3) {
            return true;
        }
        // 如果 number 是偶数且大于2,则返回false。
        if (number % 2 == 0) {
            return false;
        }
        // 计算 number 的平方根,并从5开始检查每个奇数是否能整除 number。
        // 如果能整除,则返回false;否则,最后返回true,表示 number 是素数。
        int sqrt = (int) Math.sqrt(number);
        for (int i = 5; i <= sqrt; i += 2) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }
}

2.2 埃拉托斯特尼筛法

埃拉托斯特尼筛法是一种高效的找出一定范围内所有素数的算法。

它的基本思想是逐步标记掉非素数,最后剩下的就是所有的素数。

2.2.1 原理

  1. 初始化数组:创建一个布尔数组 isPrime,长度为要寻找的最大数 n。初始化时,假设所有数都是素数,将所有元素设为 true,除了索引0和1,因为0和1不是素数。

  2. 筛除非素数:从数组的第一个素数2开始,将其所有倍数标记为非素数(设为 false)。然后找到下一个未被标记的数(下一个素数),继续将其倍数标记为非素数。重复这个过程,直到处理到 n \sqrt{n} n ​ ​ 为止。

  3. 收集素数:筛选完成后,数组中仍为 true 的索引即为素数。

2.2.2 具体步骤

  1. 创建布尔数组 isPrime,长度为 n + 1,所有元素初始化为 true
  2. 将0和1设为非素数isPrime[0] = isPrime[1] = false)。
  3. 从2开始,将2的所有倍数(除了2本身)标记为非素数。
  4. 找到下一个为 true 的数(即下一个素数),将其所有倍数标记为非素数。
  5. 重复步骤4,直到到达 n \sqrt{n} n ​ ​ 。
  6. 遍历数组,收集所有仍为 true 的索引,这些索引对应的数即为素数。

2.2.3 算法实现

public class PrimeCount {
    public static void main(String[] args) {
        int number = 1000;
        int count = countOfSuShu(number);
        System.out.println("1到" + number + "之间的素数个数是:" + count);
    }

    public static int countOfSuShu(int number) {
        if(number < 2) return 0;

        boolean[] isPrime = new boolean[number + 1];

        for(int i = 2; i <= number; i++) {
            isPrime[i] = true;
        }

        for(int i = 2; i * i <= number; i++) {
            if(isPrime[i]) {
                for(int j = i * i; j <= number; j += i) {
                    isPrime[j] = false;
                }
            }
        }

        int count = 0;
        for(int i = 2; i <= number; i++) {
            if(isPrime[i]) {
                count++;
            }
        }

        return count;
    }
}

2.2.4 示例

number = 30 为例:

  1. 初始化:isPrime = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true]

  2. 将0和1设为非素数:isPrime = [false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true]

  3. 从2开始筛选:

    • 2是素数,标记2的倍数:isPrime = [false, false, true, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]
    • 3是素数,标记3的倍数:isPrime = [false, false, true, true, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false]
    • 4已标记为非素数,跳过。
    • 5是素数,标记5的倍数:isPrime = [false, false, true, true, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, true, false]
  4. 最终:isPrime 数组中 true 的索引为 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29],表示2到30之间的素数。

2.2.5 优点

  • 高效:时间复杂度为 O(nlog⁡ log⁡n),适用于处理较大范围的素数判断。
  • 简洁:逻辑清晰易理解,代码实现简单。

2.2.6 缺点

  • 空间复杂度较高:需要一个长度为 n 的布尔数组,对于内存有限的环境可能不适用。

埃拉托斯特尼筛法是一种经典且高效的找素数算法,特别适用于处理大范围的素数查找任务。

三、输出1到1000中间有多少个素数?

3.1 试除法

public class PrimeCount {
    public static void main(String[] args) {
        int number = 1000;
        int count = countOfPrimes(number);
        System.out.println("1到" + number + "之间的素数个数是:" + count);
    }

    public static int countOfPrimes(int number) {
        int count = 0;
        for (int i = 2; i <= number; i++) {
            if (isPrime(i)) {
                count++;
            }
        }
        return count;
    }

    public static boolean isPrime(int number) {
        if (number <= 1) {
            return false;
        }
        if (number == 2 || number == 3) {
            return true;
        }
        if (number % 2 == 0) {
            return false;
        }
        int sqrt = (int) Math.sqrt(number);
        for (int i = 5; i <= sqrt; i += 2) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }
}

运行结果:

1到1000之间的素数个数是:168

3.2 埃拉托斯特尼筛法

public class PrimeCount {
    public static void main(String[] args) {
        int number = 1000;
        int count = countOfSuShu(number);
        System.out.println("1到" + number + "之间的素数个数是:" + count);
    }

    public static int countOfSuShu(int number) {
        if(number < 2) return 0;

        boolean[] isSuShu = new boolean[number + 1];

        for(int i = 2; i <= number; i++) {
            isSuShu[i] = true;
        }

        for(int i = 2; i * i <= number; i++) {
            if(isSuShu[i]) {
                for(int j = i * i; j <= number; j += i) {
                    isSuShu[j] = false;
                }
            }
        }

        int count = 0;
        for(int i = 2; i <= number; i++) {
            if(isSuShu[i]) {
                count++;
            }
        }

        return count;
    }
}

3.3 两个算法比较

  1. 时间复杂度

    • 算法一(试除法):判断一个数是否是素数的时间复杂度为 O( n \sqrt{n} n )。因此,遍历所有数的总时间复杂度为O(n n \sqrt{n} n )。
    • 算法二(埃拉托斯特尼筛法):时间复杂度为O( n log log n)。
  2. 效率

    • 算法一:对于每个数都需要进行判断,随着 number 的增大,效率会下降。
    • 算法二:通过一次遍历标记所有非素数,提高了整体效率,特别是对大范围内的数进行素数判断时,更为高效。
  3. 空间复杂度

    • 算法一:空间复杂度为 O(1),因为只需常数级别的额外空间。
    • 算法二:空间复杂度为 O(n),因为需要一个布尔数组来标记每个数是否为素数。
  4. 结论

    • 算法二(埃拉托斯特尼筛法)更优秀,因为它在处理大范围数的素数判断时效率更高。尽管需要更多的空间来存储布尔数组,但其更低的时间复杂度使其在处理1到1000之间的素数个数时,表现更加优越。
    • 在实践中,尤其是当需要计算较大范围内的素数时,埃拉托斯特尼筛法通常是首选。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式锁 Redis+RedisSon

文章目录 1.什么是分布式锁2.分布式锁应该具备哪些条件3.分布式锁主流的实现方案4.未添加分布式锁存在的问题4.1测试未添加分布式锁的代码通过jmeter发送请求4.2 添加线程同步锁集群部署配置nginx修改jmeter端口号4.3 使用redis的setnx命令实现分布式锁解决办法4.4 使用try、fi…

【2025留学】德国留学真的很难毕业吗?为什么大家不来德国留学?

大家好&#xff01;我是德国Viviane&#xff0c;一句话讲自己的背景&#xff1a;本科211&#xff0c;硕士在德国读的电子信息工程。 之前网上一句热梗&#xff1a;“德国留学三年将是你人生五年中最难忘的七年。”确实&#xff0c;德国大学的宽进严出机制&#xff0c;延毕、休…

【日常设计案例分享】通道对账

今天跟同事们讨论一个通道对账需求的技术设计。鉴于公司业务线有好几个&#xff0c;为避免不久的将来各业务线都重复竖烟囱&#xff0c;因此&#xff0c;我们打算将通道对账做成系统通用服务&#xff0c;以降低各业务线的开发成本。 以下文稿&#xff08;草图&#xff09;&…

正点原子imx6ull-mini-Linux设备树下的LED驱动实验(4)

1&#xff1a;修改设备树文件 在根节点“/”下创建一个名为“alphaled”的子节点&#xff0c;打开 imx6ull-alientek-emmc.dts 文件&#xff0c; 在根节点“/”最后面输入如下所示内容 alphaled {#address-cells <1>;#size-cells <1>;compatible "atkalp…

昇思25天学习打卡营第1天|快速入门实操教程

昇思25天学习打卡营第1天|快速入门实操教程 目录 昇思25天学习打卡营第1天|快速入门实操教程 一、MindSpore内容简介 主要特点&#xff1a; MindSpore的组成部分&#xff1a; 二、入门实操步骤 1. 安装必要的依赖包 2. 下载并处理数据集 3. 构建网络模型 4. 训练模型…

WIN下的文件病毒

文件病毒 一.windows下知识句柄禁用某些警告MAX_PATH_WIN32_FIND_DATAWFindFirstFileW注册到服务代码&#xff08;自启动&#xff09;隐藏窗口 二.客户端代码三.服务端代码 一.windows下知识 句柄 相当于指针&#xff0c;用来表示windows下的一些对象&#xff1b; 禁用某些警…

vue3中使用ant-design-vue

ant-design-vue官网&#xff1a;Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.jsAn enterprise-class UI components based on Ant Design and Vuehttps://www.antdv.com/components/overview-cn/ 安装 npm i -S ant-design-vue 引入 …

前端实现【 批量任务调度管理器 】demo优化

一、前提介绍 我在前文实现过一个【批量任务调度管理器】的 demo&#xff0c;能实现简单的任务批量并发分组&#xff0c;过滤等操作。但是还有很多优化空间&#xff0c;所以查找一些优化的库&#xff0c; 主要想优化两个方面&#xff0c; 上篇提到的&#xff1a; 针对 3&…

“数说”巴黎奥运会上的“中国智造”成果

引言&#xff1a;随着“中国智造”在欧洲杯上方兴未艾&#xff0c;在巴黎奥运会上&#xff0c;中国智造继续以多种形式和领域展现了其强大的实力和创新能力。以格力公开表示将为巴黎奥运村提供345台格力空调&#xff0c;为中国制造的清凉送至巴黎事件拉开中国制造闪亮巴黎奥运会…

CTF Web SQL注入 10000字详解

这里写目录标题 涉及的数据库知识unionorder bydatabase()information_schemalimit--空格注释replaceinto outfilelikeGROUP BYHAVINGGROUP BY、HAVING、WHERE之间的关系regexp 原理信息收集操作系统数据库判断注入点注入点类型POST注入数字型注入字符型注入搜索型注入Insert/u…

Debian12 安装Docker 用 Docker Compose 部署WordPress

服务器准备&#xff1a; 以root账号登录&#xff0c;如果不是root&#xff0c;后面指令需要加sudo apt update apt install apt-transport-https ca-certificates curl gnupg lsb-release添加GPG密钥&#xff0c;推荐国内源 curl -fsSL https://mirrors.aliyun.com/docker…

ArchLinux部署waydroid

在Arch Linux系统上部署Waydroid运行Android APP 文章目录 在Arch Linux系统上部署Waydroid运行Android APP1. 安装要求2. 本机环境3. 安装 Waydroid4. 网络配置5.注册Google设备6. 运行效果图 Waydroid是Anbox配合Haliun技术开发的LXC Android容器&#xff0c;可在GUN/Linux系…

C语言中的指针基础

文章目录 &#x1f34a;自我介绍&#x1f34a;地址&#x1f34a;C语言中的指针 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xff08;一键四连&#xff09;哦~ &#x1f34a;自我介绍 Hello,大家好&#xff0c;我是小珑也要变强&am…

Spring Boot 3 + Resilience4j 简单入门 + Redis Cache 整合

1. 项目结构 2. Maven依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.2</version><relativePath/> <!-- lookup parent from repository --&…

CSRF Token 原理

CSRF 攻击 CSRF 攻击成功的关键是&#xff0c;恶意网站让浏览器自动发起一个请求&#xff0c;这个请求会自动携带 cookie &#xff0c;正常网站拿到 cookie 后会认为这是正常用户&#xff0c;就允许请求。 防范 如果在请求中加一个字段&#xff08;CSRF Token&#xff09;&am…

C++笔记之指针基础

函数重载:(C++特性) 定义: C++允许函数重名,但是参数列表要有区分 在相同的作用域定义同名的函数,但是它们的参数要有所区分,这样的多个函数构成重载关系 objdump -d test.exe >log.txt 将test.exe反汇编并将结果重定向到log.txt 文件中 ,然后在 log.txt中找到定…

学习网络安全 为什么Linux首择Kali Linux? 以及如何正确的使用Kali Linux

1.什么是kali linux&#xff1f; Kali Linux是一款基于Debian的Linux发行版&#xff0c;主要用于网络安全测试和渗透测试。它由全球顶尖的安全专家和黑客社区维护开发&#xff0c;提供了丰富的工具和资源&#xff0c;用于测试安全性、漏洞利用和渗透测试。此外&#xff0c;Kal…

MySQL 性能调优

文章目录 一. MySQL调优金字塔1. 架构调优2. MySQL调优3. 硬件和OS调优4. 小结 二. 查询性能调优三. 慢查询1. 概念2. 优化数据访问3. 请求了不需要数据&#xff0c;怎么做4. 是否在扫描额外的记录5. 慢查询相关配置 & 日志位置6. 小结 四. 查询优化器五. 实现调优手段 一.…

24、Python之面向对象:责任与自由,私有属性真的有必要吗

引言 前面我们进一步介绍了类定义中属性的使用&#xff0c;今天我们对中关于属性私有化的话题稍微展开聊一下&#xff0c;顺便稍微理解一下Python设计的相关理念。 访问级别 在其他编程语言中&#xff0c;比如Java&#xff0c;关于类中的属性和方法通过关键字定义明确的访问级…

1、仓颉工程基础操作 cjpm

文章目录 1. 仓颉工程创建方式2. cjpm2.1 init 初始化工程2.2 run 运行工程 1. 仓颉工程创建方式 使用 cangjie studio 通过cangjie studio 创建 使用vscode插件 通过 VSCode 命令面板创建仓颉工程通过可视化界面创建仓颉工程 cjpm 注&#xff1a;具体使用参考官方文档&#…