【问题标题】:Why is algorithm time complexity often defined in terms of steps/operations?为什么算法时间复杂度通常以步骤/操作来定义?
【发布时间】:2021-04-08 08:34:42
【问题描述】:

我最近从许多不同的资源中对算法分析进行了大量研究,我目前感到困惑的一件事是,为什么时间复杂度通常根据算法执行的步骤/操作数来定义。

例如,在 Cormen 的 Introduction to Algorithms, 3rd Edition 中,他指出:

算法在特定输入上的运行时间是执行的原始操作或“步骤”的数量。定义 step 的概念很方便,使其尽可能独立于机器。

我已经看到其他资源也定义了时间复杂度。我对此有疑问,因为首先,它被称为时间复杂度,而不是“步骤复杂度”或“操作复杂度”。其次,虽然它不是一个确定的来源,但 answer 在 Stackoverflow 上的一篇文章中指出“运行时间是程序运行所需的时间。时间复杂度是对运行时间的渐近行为的描述,因为输入大小趋于无穷。”此外,在Wikipedia page 的时间复杂度上,它指出“在计算机科学中,时间复杂度是描述运行算法所需的计算机时间量的计算复杂度。”同样,这些都是确定的来源,使用这些定义是合乎逻辑的。

在分析算法并推导其时间复杂度函数时,如下图 1 所示,您会得到一个以时间为单位的方程。它可以表示算法执行的运算量,但前提是这些常数因子(C_1、C_2、C_3 等)的值均为 1。

图1

综上所述,我只是想知道如何将其定义为步骤数,而实际上这并不是它所代表的含义。我正在尝试清理事情并在时间和操作次数之间建立联系。我觉得有很多信息在我研究过的资源中没有明确说明。希望有人可以帮助我解决问题,并且无需讨论 Big-O,因为在我看来,这是不需要的,并且错过了问题的重点。

感谢大家的时间和帮助。

【问题讨论】:

  • 一个很大的原因是不同的计算机配置支持不同的操作时间,因此 CPU 性能的变化直接影响相同 nr 操作执行的速度
  • Computer Science 可能会更好,如果您同意,请标记要迁移的模组

标签: algorithm


【解决方案1】:

为什么时间复杂度通常以算法执行的步骤/操作数来定义?

TL;DR: 因为这就是asymptotic analysis 的工作方式;还有,别忘了time is a relative thing


更长的故事:

及时测量性能,因为我们人类在日常使用中理解时间,但这并没有多大意义,因为它并不总是那么微不足道的任务......此外 - 它甚至在更广泛的范围内没有任何意义观点。

您将如何衡量您的算法所花费的空间和时间?您将应用什么条件和预定义的测量单位来查看算法的运行时间/空间复杂度?

您可以在时钟上测量它,或者使用一些库/API 来查看准确您的算法花费了多少秒/分钟/兆字节......等等。

然而,这一切都将是非常多变的!因为,您的算法所花费的时间/空间将取决于:

  1. 您正在使用的特定硬件(架构、CPU、RAM 等);
  2. 特定的编程语言;
  3. 操作系统;
  4. 编译器,您曾经将高级代码编译成较低的抽象;
  5. 其他特定于环境的详细信息(有时,甚至是温度……因为 CPU 可能会动态调整工作频率)……

因此,以精确的时间来衡量您的复杂性并不是一件好事(同样,我们了解这个星球上的时间)。

那么,如果您想知道算法的复杂度(比如说时间复杂度),为什么对不同的机器、操作系统等设置不同的时间有意义呢?算法复杂性分析不是关于测量特定机器上的运行时间,而是关于为最佳、平均和最差情况提供清晰且数学定义的精确边界。

我希望这是有道理的。

好的,我们终于明白了,算法分析应该作为一个独立的数学复杂性分析来完成。它不会关心机器、操作系统、系统架构或其他任何东西(除了算法本身) ,因为我们需要观察逻辑抽象,而不关心您是在 Windows 10、Intel Core2Duo 还是 Arch Linux、Intel i7 或您的手机上运行它。

还剩下什么?

算法分析的最佳(迄今为止)方法是进行渐近分析,这是基于输入计算的抽象分析......并且计算几乎所有步骤和算法中执行的操作,与您的输入成比例。

这样你就可以谈论算法本身,而不是依赖于周围的环境。


此外;我们不仅不应该关心机器或外围因素,我们也不应该关心渐近分析的数学表达式中的低阶项常数因素

常数因子:

常数因子是独立于输入数据的指令。即不依赖于输入参数数据。

您应该忽略它们的几个原因是:

  1. 不同的编程语言语法,以及它们的编译文件,会有不同数量的常量操作/因子;
  2. 对于相同的常数因子,不同的硬件会给出不同的运行时间。

因此,您应该消除分析常数因素的想法,并否决/忽略它们。只关注与投入相关的重要因素;因此:

  1. O(2n) == O(5n) 所有这些都是O(n);
  2. 6n2 == 10n2 所有这些都是 n2.

我们不关心常数因子的另一个原因是,我们通常希望测量足够大输入的复杂性。当输入增长到 + 无穷大时,是否有 n 真的没有意义或 2n。

低阶项:

类似的概念也适用于这一点:

根据定义,当您关注大量输入时,低阶术语变得越来越不相关。

当您有 5x4+24x2+5 时,您永远不会太在意小于 4 的指数。

【讨论】:

    【解决方案2】:

    时间复杂度不是以秒为单位衡量一个算法需要多长时间。这是关于比较不同的算法,如果输入数据,它们将如何执行一定的数量。以及当输入数据变大时这种性能如何发展。

    在这种情况下,“步数”是时间的抽象概念,可以独立于任何硬件进行比较。即,如果没有确切的硬件规格(以及一个步骤需要多长时间),您无法确定执行 1000 步需要多长时间。但你总能看出,执行 2000 步所需的时间大约是执行 1000 步的两倍。

    如果不讨论 Big-O,就无法真正讨论时间复杂度,因为它就是这样。

    【讨论】:

      【解决方案3】:

      您应该注意,算法比程序更抽象。您在论文或书籍上检查了两种算法,并且想要分析哪种算法对大小为 N 的输入数据更快。因此,您必须用逻辑和语句分析它们。您也可以在计算机上运行它们并测量时间,但这不能证明。

      此外,不同的计算机以不同的速度执行程序。这取决于 CPU 速度、RAM 和许多其他条件。根据可用资源的不同,即使是单台计算机上的程序也可能以不同的速度运行。

      因此,算法的时间必须与在特定计算机上执行单个原子指令所需的时间无关。它被认为只是一步或O(1)。此外,我们对常量不感兴趣。例如,一个程序有 2 条还是 10 条指令都没有关系。两者都将在几微秒内运行。通常,指令的数量是有限的,并且它们都在计算机上运行得很快。重要的是指令或循环的执行取决于变量,这可能是程序输入的大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-04
        • 1970-01-01
        • 1970-01-01
        • 2022-12-03
        • 2021-06-27
        • 2022-01-09
        • 2020-09-12
        • 1970-01-01
        相关资源
        最近更新 更多