很容易看出n!增长得比几乎任何N的幂次方(例如100^N)都要慢,因此,如果一个问题被认为是NP完全的,并且我们找到了一个n!算法来近似解决方案,那么人们会为之欢呼雀跃。
我对这种情况有两个问题:
- n!算法是否可以被认为是多项式时间内的解法?阶乘显然不是一个幂次方的项。
- 如果找到了n!解决方案意味着我们拥有了一个相当快的算法并且n!增长得比2^N要快,那么这是否意味着一些NP完全问题不需要启发式/近似算法(除了少数例外)?
当然,这两个问题基于第一段话是正确的;如果我犯了错误,请告诉我。
很容易看出n!增长得比几乎任何N的幂次方(例如100^N)都要慢,因此,如果一个问题被认为是NP完全的,并且我们找到了一个n!算法来近似解决方案,那么人们会为之欢呼雀跃。
我对这种情况有两个问题:
当然,这两个问题基于第一段话是正确的;如果我犯了错误,请告诉我。
不,阶乘时间复杂度不是多项式时间复杂度。多项式时间复杂度通常意味着形如O(Nk)的方程式,其中N为处理的项数,k为某个常数。重要的是指数是一个常数——你正在将N乘以一个固定数量的自身——而不是取决于N本身。阶乘时间复杂度算法意味着乘法的数量并不固定——乘法的数量随着N增长。
在这里你似乎有同样的问题。N2将是多项式时间复杂度。2N则不是。你的基本前提也是错误的——阶乘时间复杂度算法并不意味着“我们有一个相当快的算法”,至少一般来说不是这样。如果有什么的话,结论恰恰相反:阶乘算法可能在一些特殊情况下实用(即,N非常小), 但是随着N的增长,它很快变得不实用。
让我们来看看这个问题。二分查找的时间复杂度为O(log N)。线性搜索的时间复杂度为O(N)。在排序中,“慢”算法的时间复杂度为O(N2),而“先进”的算法则是O(N log N)。阶乘时间复杂度就是(显然)O(N!)。
让我们尝试将其放在一个更具体的背景下。考虑到只处理10个项,每个项大致上应该比1个项需要花费多少倍的时间:
O(log N): 2
O(N):10
O(N log N): 23
O(N2): 100
O(N!): 3,628,800
这里我稍微作弊了一点,使用了自然对数而不是以2为底的对数,但我们只是在试图提供一个粗略的估计(而且差异在任何情况下都是一个相当小的常数因素)。
如您所见,阶乘复杂度算法的增长速率比其他任何算法都要快得多。如果我们将其扩展到20个项目,则差异会更加明显:
O(log N):3
O(n):20
O(N log N):60
O(N2):400
O(N!):2,432,902,008,176,640,000
N!的增长速度非常之快,以至于它们几乎保证在涉及的项目数量已知相当小时就会变得不实用。仅仅为了好玩,让我们假设上述过程的基本操作可以在单个机器时钟周期内运行。出于论证的目的(并且为了保持计算简单),让我们假设有一个10 GHz的CPU。那么,处理一个项目需要0.1纳秒。在这种情况下,有20个项目:
O(log N) = 0.3 纳秒
O(N) = 2 纳秒
O(N log N) = 6 纳秒
O(N2) = 40 纳秒
O(N!) = 7.7 年。
很容易看出阶乘在行为上是(近似)指数级的。
它可以(非常粗略地)近似为nn(更具体地说,是sqrt(2πn)(n/e)n)。
因此,如果你找到了任何特定的M,认为Mn是一个好的近似值,那么你(可能)是错误的。269!比100n还要大,并且由于n!将与大于100的数字相乘,它将继续增长得更快。