素数表在算法中经常会用到,所以掌握一种高效求解素数表的算法是很有必要的。
这里介绍一种算法:筛法。筛法的时间复杂度我不太清楚,但我知道是接近于 O(n) 的,比一般的求解素数的算法效率要高很多,其基本思想如下:
1、要得到 2 — n 之间的所有素数,先记录下 2 — n 之间的所有整数,用集合表示 A = { 2 , 3 , 4 , 5 , 6 …… n }
2、创建一张素数表 PrimeTable ,刚开始表中是空的。用集合表示 PrimeTable = { }
3、挑选出 A 中最小的数 min ,加入 PrimeTable 。删除 min 的所有倍数。第一次挑选的时候,min = 2 ,把 2 加入到PrimeTable中并删除 2 的所有倍数后,集合 A = { 3 , 5 …… n } ,PrimeTable = { 2 }
4、重复步骤 3 ,直到集合 A 空了为止。这时也就生成了 2 — n 之间的素数表 PrimeTable = { 2 , 3 , 5 …… }
参考代码:
public class PrimeTable { // 常量,为了表示2—10000这个范围 static final int CONSTANT = 10000; // A[0]不用,下标代表的就是2—10000之间的某个数 static final int[] A = new int[CONSTANT + 1]; // 1229是因为事先我已经知道了2—10000之间有1229个素数,不知道的时候可以定义大一些 static int[] PrimeTable = new int[1229]; private static void createPrimes() { for (int i = 2; i <= CONSTANT; i++) { // A[i]==0代表i之前没有被删除,是个素数;A[i]==1代表之前被删除了,不是素数;不是素数也就没必要再计算了 if (A[i] == 0) { // i是素数的时候,删除所有i的倍数,赋值为1代表删除 for (int j = i * 2; j <= CONSTANT; j += i) { A[j] = 1; } } } // 上面的for循环已经把A中的素数下标代表的A[i]赋值为0,合数下标代表的A[i]赋值为1了 // 下面的for循环就是把A中的所有素数放到素数表PrimeTable中了 int k = 0; for (int i = 2; i <= CONSTANT; i++) { if (A[i] == 0) { PrimeTable[k++] = i; } } } // 主函数 public static void main(String[] args) { createPrimes(); for (int i = 0; i < PrimeTable.length; i++) { System.out.println(PrimeTable[i]); } } }
原文地址:http://blog.csdn.net/u011506951/article/details/26146595