Algorithm 我的函数是O(n!),还是O((n-1)!)更精确?

Algorithm 我的函数是O(n!),还是O((n-1)!)更精确?,algorithm,time-complexity,big-o,Algorithm,Time Complexity,Big O,我已经为旅行推销员问题编写了一个蛮力搜索算法,并对其进行了测试,以查看不同数量的“城市”所需的时间。从下图中,我们可以看到时间大致与(n-1)成正比其中n是“城市”的数量。它与n不成正比(毕竟,(n-1)!=n!/n) 我的问题是,说算法在O(n!)中运行还是说O((n-1)!)更好?我以前从未见过后者,但它似乎更准确。我好像误解了什么 [t=所用时间,n=城市数量]O(n!)就足够了n或n-1对大型n没有影响 看 例如 根据定义,O(f(n))是由f(n)渐近支配的所有函数的集合,即所有函数

我已经为旅行推销员问题编写了一个蛮力搜索算法,并对其进行了测试,以查看不同数量的“城市”所需的时间。从下图中,我们可以看到时间大致与
(n-1)成正比其中
n
是“城市”的数量。它与
n不成正比(毕竟,
(n-1)!=n!/n

我的问题是,说算法在
O(n!)
中运行还是说
O((n-1)!)
更好?我以前从未见过后者,但它似乎更准确。我好像误解了什么

[t=所用时间,n=城市数量]

O(n!)
就足够了
n
n-1
对大型
n
没有影响

看 例如

根据定义,O(f(n))是由f(n)渐近支配的所有函数的集合,即所有函数g(n)的集合,其中有常数C和n_0,使得

g(n) < C * f(n)   for all n > n_0
g(n)n\u 0
根据这个定义,O(n!)实际上是O((n-1)!)的超集,因为函数f(n)=n!是第一个集合的成员,但不是第二个集合的成员。这两套实际上并不相同

不过,说你的问题是O(n!)是正确的,因为这只说明了一个上边界。说你的问题是ϴ(n!)是不正确的,因为这表示常数因子的精确渐近行为


实践中没有大的区别,正如另一个答案所指出的,你可以重新定义n,表示城市数量减去1。

你可以简单地证明如下:

O((n-1)!)表示存在常数c,例如:

算法步骤(或时间复杂度)1

因此,由于for complexity函数的算法保持不变: 算法步骤(或时间复杂度) 你的算法也是O(n!)


因此,我们证明了如果算法的时间复杂度是O((n-1)!),那么它也是O(n!)。

Sven Marnach的答案非常好,我只想在这一部分详细说明一下:

还是我说O((n-1)!)更好

正如其他人所说,
O(n)
通常已经足够好了。如果您确实想了解有关问题的更多信息,您可以尝试查找并证明:

  • 下限(通常用
    Ω(n)
    表示)
  • 严格的上限
下界基本上是说,在某些假设下,不可能有算法渐近更快地解决问题。紧上界是与下界匹配的上界,即,必须证明
Ω(f(n))
的下界和
O(f(n))
的上界。如果你能证明一个下界和一个紧上界,这意味着你的算法是这个问题的渐近最优算法


举一个具体的例子:你肯定知道像merge-sort或quick-sort这样的排序算法,以及它们的上界
O(n logn))
。Donald Knuth(几十年前)指出,基于比较的整数排序算法至少需要
n logn
比较,即
Ω(n logn)
操作。因为我们有一个匹配的上界,合并排序和快速排序都被认为是渐近最优的(尽管它们的性能在实践中有很大的不同)。

比如,一个大值是
n=100
,然后
O(n!)=9.33*10^157
,其中
O((n-1)!=9.33*10^155
。你认为这两者之间没有区别吗??)它们都是“大得像地狱一样,无论如何都不能用于大n”。所以,事实上没有区别:)这两个数字都比宇宙中估计的原子数(仅为10^81)还要大。@jbsu32,这简直是胡说八道
O(…)
是一类函数,不能等于数字。是的,
O(10n)=O(n)
,所以对于
O
-符号,
O(f(n))
是一类函数,类似于偶数或可微函数,在
3990万
360万
之间没有区别。@jbsu32,
O(f(n))
是一类函数。斯文(或在数学书中)解释了这门课的具体内容。如果我们把类看作是属于这个类的所有函数的集合(共同概念),那么是的,
O(10n)=O(n)=O(10^100n)
,因为它们的元素是相同的。@jbsu32,O(10n)总是等于O(n),因为我们不关心常数因子这个答案使用了正确的方法。事实上,人们通常有
O(f(n))=O(f(n-1))
——例如,如果
f
是多项式或指数,这是正确的。然而,如上所述,并非所有函数都是如此:我们有
limn/(n-1)!=lim n=infty
表示
n->infty
。对。我不太同意
f(n)
f(n-1)
之间的“在实践中没有大的区别”——当函数的增长速度和阶乘一样快的时候就不行了!这样,可以说任何Θ(n!)算法只适用于非常小的输入;你永远不会有机会把
n
做得太大,以至于一个或多或少都是无关紧要的。“你可以重新定义n来表示城市数量减去一。”这是一个坏主意,因为这会导致混乱。为什么不把它定义为sqrt(| cities |)?Big-O符号的可能重复并不是为了实际提供算法的计算,而是为了提供它们之间的抽象比较方法。算法的最终行为是阶乘-它恰好是+1或-1这一事实无关紧要。