细节输出质数

248 阅读3分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战

大家好,我是洋哥。今天给大家带来的是每日一题——细节输出质数。

题目要求

通过Java程序流程控制的学习,相信你已经能够熟练使用各种循环语句了,下面请用你学过的循环语句输出100000以内的质数。

 

建议用时:10-15分钟

难度:中等

 

知识点考察

这道题考察的是for循环的嵌套循环,但这不是我这次想说的重点,我这次想说的还是算法的问题,同一个问题用不同方法效率差别很大,尤其是复杂问题,数据量大的问题。

 

问题分析

第一,我们来看一下这个问题的解决方法。首先外层一个for循环,用来遍历2-100000的数字,内层for循环来判断是否为质数。设外层数字用i表示,用i对小于i的数字(用j表示)一一取余i%j,如果等于0,即不是质数,否则继续,因为这个判断不是一次的,所以我们要在外层定义一个boolean类型的isflag来表示真伪,如果有一次i%j==0,就让isflag=false,再用条件判断来确定是输出还是不输出。问题到这就解决了?没有。

 

第二,第一个优化点。当判断出i%j==0时,直接用break跳出循环,不用在判断当为其他的j时,i%j是否等于0,因为只要有一个等于0,他就不是质数了,我测试了一下,原始方法执行需要12316ms,优化后只需1265ms,直接缩短至1/10。

 

第三,第二个优化点。我们不需要对小于i的所有数字一一取余,只需要取余至sqrt(i)即可,因为因子都是成对出现的。我又测试了一下,改进后只需要62ms,又提升了10倍的效率。

 

   

相关知识点复习

嵌套循环(多重循环)

将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while均可以作为外层循环内层循环

算法的提升:对于可以省略的步骤尽可能的简化省略,减少不必要的计算过程。

   

代码实现

package com.control.contact;
public class PrimeNumberTest2 {


	public static void main(String[] args) {


		boolean isFlag=true;
		
		//获取当前时间距离1970-1-1 00:00:00的毫秒数
		long start=System.currentTimeMillis();
		for(int i=2;i<=100000;i++){  //遍历100以内的自然数
			
			for(int j=2;j<=Math.sqrt(i);j++){
				if(i%j==0){
					isFlag=false;
					break;
				}
				
			}
			
			if(isFlag==true){
				System.out.println(i);
			}
			//重置isFlag
			isFlag=true;
		}
		
		//获取当前时间距离1970-1-1 00:00:00的毫秒数
				long end=System.currentTimeMillis();
		System.out.println("所花费的时间为"+(end-start));	
	}
}

   

总结和建议

我们现在的计算机性能很好,内存很大,cpu也很强,但是我们就不需要追求效率了吗?不是的,追求高效其实就是追求好的算法,对于一个简单问题算法的优劣可能体现不出什么,但是对于重要复杂数据量大的问题,一个好的算法的价值是不可估量的,追求好的算法也是对我们逻辑思维的训练。