华为有道面试题:
在十秒钟之内,找到一到一百万个数中的所有素数。
首先解释一下什么是素数:只能被1和它自身整除的数是素数。0和1不是素数。2是素数。
接到这道题后我们首先排除掉能被2、3、5、7这几个数整除的数。这样一排除,一百万个数只剩下228573个数。减少了大概五倍的运算量。
然后再去遍历找出其他的。
话不多说,上代码
public class CalculationPrime {
private static Set<Integer> set = new HashSet<>();
private static final int boss = 1000000;
static {
for (int i = 3; i < boss; i++) {
set.add(i);
}
}
public static void main(String[] args) {
long data = System.currentTimeMillis();
calculation(2);
calculation(3);
calculation(5);
calculation(7);
System.out.println(getPrime() + "个数字");
printData(data);
}
/**
* h获取素数
*
* @return
*/
public static Integer getPrime() {
Iterator<Integer> integers = set.iterator();
Integer i = null;
while (integers.hasNext()) {
i = integers.next();
if (checkPrime(i)) {
integers.remove();
}
}
set.add(2);
return set.size();
}
/**
* 判断是否是素数
*
* @param i
* @return
*/
public static boolean checkPrime(Integer i) {
for (int j = 3; j <= Math.sqrt(i); j++) {
if (i % j == 0) {
return true;
}
}
return false;
}
/**
* 排除一些数字
*
* @param factor
*/
public static void calculation(int factor) {
Iterator<Integer> integers = set.iterator();
Integer i = null;
while (integers.hasNext()) {
i = integers.next();
if (i % factor == 0 && factor != i) {
integers.remove();
}
}
}
public static void printData(long oldData) {
long currentData = System.currentTimeMillis();
System.out.println("共运行" + ((currentData - oldData)) + "毫秒");
}
}
运行结果为
这里的关键在于找素数的循环条件,如果采用了 Math.sqrt(i),整个程序循环运行次数为66183273。六千多万次。
而如果采用折半(i/2)这种条件的话,循环运行次数为1610816911。
十六亿次。
两者足足相差了两个量级,可见掌握一定的数学知识对于编程性能的提升有着巨大的好处。