【发布时间】:2012-03-15 07:04:05
【问题描述】:
我需要打印所有小于给定数 n 的素数。我可以使用 Eratothenes 的筛子,但该算法的运行时间不是 O(n)。这个问题有O(n)时间解吗?
【问题讨论】:
标签: primes
我需要打印所有小于给定数 n 的素数。我可以使用 Eratothenes 的筛子,但该算法的运行时间不是 O(n)。这个问题有O(n)时间解吗?
【问题讨论】:
标签: primes
埃拉托色尼筛法的时间复杂度为 O(n log log n)。函数 log log n 增长非常缓慢;例如,log(log(10^9)) = 3。这意味着您可以有效地将时间复杂度的 log log n 部分视为常数,并忽略它,给出“几乎” O(n) 的时间复杂度.
有多种算法可以在 O(n) 或 O(n / log log n) 时间内运行,包括 Pritchard 轮筛和 Atkins 筛。但常数因素通常会使这些算法在实践中比埃拉托色尼筛法慢。除非您需要极高的速度,并且您知道自己在做什么,并且愿意花费大量时间去做,否则实际的答案是埃拉托色尼筛。
您的问题是要打印素数列表。在这种情况下,输出将支配您选择的任何算法的运行时间。所以帮自己一个忙,实现一个简单的 Eratosthenes 筛。
【讨论】:
我认为您不会找到一种算法来检查具有 O(n) 时间复杂度的 任意 数的素性。我很确定 NSA(以及任何其他处理加密问题的组织)不会对此很满意 :-)
获得 O(n) 或更好的方法的唯一方法是预先计算(例如)前 5000 万个素数(或使用 someone else's already-precalculated list)并将其用作查找。我在本地有这样一个文件,只需在其上运行grep 即可查看该数字是否为素数。它对任意数字没有帮助,但我很少需要使用那么大的数字。当然,加密货币的人会认为这样一个列表对于他们的目的来说太小了。
而且,如果将其转换为位图(前 500 万个素数约为 120M),您甚至可以通过简单地将数字转换为字节偏移量和位掩码将复杂度降低到 O(1) - 一对位移和/或按位运算。
但是,在 O(n) 时间复杂度中,获得低于某个n 的素数的列表 肯定是可行的。 Atkin and Bernstein paper 详细说明 Sieve of Atkin 声明:
我们引入了一种算法,该算法使用
O(N/log(log(N)))加法计算最多为 N 的素数 ...
这实际上比 O(n) 略好。
但是,它仍然不太可能与查找解决方案竞争。我的建议是使用 Atkin 或 Eratosthenes 来制作一个列表 - 这并不重要,因为您只会这样做一次,因此性能并不重要。
然后使用列表本身来检查素数。
【讨论】:
grep 用于第 50 百万个素数的时间不到半秒。筛子花费了 1 分 10 秒,尽管可以说它现在知道低于该数字的 所有 素数,但使用稍微复杂的搜索词或使用 @ 的 grep 解决方案也是如此987654330@ 获取行号,head 将它们全部打印出来)。特定值的试除法要快得多,但是一旦您离开本机整数领域并使用 bignum 库,这可能会减慢很多。