用于加载5100万个素数然后迭代它们的任务的最佳数据结构(在java中)是什么?
我需要知道,例如,在1000000000和相同数字减去100000之间的素数。
答案 0 :(得分:6)
二进制搜索对于这些数据来说并不是很好,因为素数的前半部分将比它们的后半部分更接近彼此。
您可以通过了解how many primes there are under x来改进搜索。也许使用链接中提到的近似值来削减切割。
我的第一次尝试就是这样。我有两个阵列。
在对数组1做任何事情之前,我会得到数组2的粗略位置。
答案 1 :(得分:3)
为什么要将它们存放在地图中?这是为了让您快速查找以查看是否有任何给定数字是素数?这将是有道理的,并为您提供快速访问。通过设置TreeMap的初始容量,可以减轻(但不能消除)添加它们的成本。然而,这仍将导致树再平衡成本。
替代存储可能只是对它们进行排序并将它们放入数组中。这将使您通过二分搜索进行O(log n)查找,但会使得范围变得微不足道。您可以使用Arrays.binarySearch()。
答案 2 :(得分:3)
既然你可以预先计算所有素数,并且(通过Nosredna和其他人提到过的素数定理)你知道将会有多少素数,你可以使用一个固定的结构(int [])和一次性订单插入成本不应该是一个问题。
二进制搜索(As Arrays.binarySearch())会非常快,您可能不需要考虑优化。但是,你也可以使用素数定理的大致预测,即Nth prime更快地找到范围的端点。
只是为了与众不同,我要指出,在这个比例下,您还可以将素数作为设置位存储在一个大位域中,其中如果N是素数,则位#N设置为1.结构实际上是小于int [] - 10亿比特是~110MiB,而5100万比特是〜200MiB。请参阅类BitSet。因为没有偶数索引是素数,所以你可以子类化或包装BitSet,在传递到/从BitSet传递之前,为所有偶数索引和半/双值提供简单的答案,从而将整个字段存储在~55MiB中。
使用这样的结构测试素数是O(1),但迭代所有设置位(素数)取决于您所针对的范围中质数的密度。它仍然应该很快。
答案 3 :(得分:1)
对我来说,一个简单的数组(或ArrayList,因为它更容易使用)会很好。添加元素是O(1),您可以通过对第一个素数> = x(参见http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collections.html#binarySearch%28java.util.List,%20T%29)进行二元搜索来获得x和y之间的所有素数,然后只需通过列表直到获得到一个黄金>年。
(我意识到cletus打败了我,但希望额外的细节有用。)
答案 4 :(得分:1)
第n个素数约为p(n) ~ n ln(n)
,即
p(51E6) ~ 905114146 < 2147483647 = Integer.MAX_VALUE
这意味着存储前5100万个素数的最有效方法是int[]
。
答案 5 :(得分:1)
这完全取决于操作和使用的平衡。一个简单的排序数组最适合存储素数。
现在,如果性能真的很高,内存成本微不足道,那么你可以用索引索引来增加它。 e.g。
int MAX_NUM_PRIMES = ... // the maximum number of primes to be stored
int MAX_PRIME = .... // the largest prime to be stored
int primes[MAX_NUM_PRIMES] // array of prime numbers, sorted
int nextPrime[MAX_PRIME] // nextPrime[i] is the index of the next prime >= i
where nextPrime[i] is the starting point in the array primes for the first prime > i.
then, to iterate over e.g. 2000 primes from 3456, you would do
int j = nextPrime[3456]
for (i = j; i < j + 2000; i++) {
int x = prime[i];
... do whatever with x ...
}
答案 6 :(得分:1)
我需要知道,例如,在1000000000和相同数字减去100000之间的素数。
然后为你感兴趣的那些数字构建一个筛子。计算下面的所有素数都是浪费,除非你想知道999900000以下有多少素数。
这个数字大小的良好数据结构是有点设置的。因为大约21个数字中的一个是素数,它比显式存储数字所需的内存更少,并且它足以快速遍历范围。
编辑:具体来说,在我的笔记本电脑上用Java筛选整个范围需要花一点多时间,筛选最后100000大约30毫秒。
答案 7 :(得分:0)
如果你想要最好的数据结构来快速找到x和y之间的素数(如你的例子中所示),你需要一个二进制索引树。
有一个很好的描述here。
答案 8 :(得分:0)
这个java applet看起来相当快:Prials表从1到1 000 000 000 000 http://www.walter-fendt.de/m14e/primes.htm(虽然没有来源,但你可能会尝试作者)
答案 9 :(得分:0)
一组数字可能会很好:)
问题可能是生成数组?在这种情况下,创建一个包含数组的对象并填充它(通过生成它们或从素数列表中读取)。完成后,将其序列化为磁盘,以便程序可以在将来快速读取二进制流以加载阵列。
有关如何生成素数组的变体,请参阅此问题:Prime number calculation fun
答案 10 :(得分:0)
根据您的要求,您应该使用Eratosthenes的分段筛。它不需要大量的内存..
查找所有素数到999900000的平方根。(~31,621) 它可以很容易地存储在数组中。
现在,在100000长度的阵列上执行筛分过程。这些素数。
对于大数字而言效率很高。