【问题标题】:What does "in constant time" imply?“在恒定时间内”是什么意思?
【发布时间】:2011-05-18 23:17:22
【问题描述】:

我是一名程序员,但没有计算机科学背景,所以最近我一直在关注优秀的 MIT OpenCourseWare 计算机科学和编程入门课程。在此过程中,有人问:“任何仅使用函数定义和调用、基本算术运算符、赋值和条件编写的程序都会在恒定时间内运行吗?”

我认为答案是肯定的,因为所有这些操作看起来都很简单。但正如你们聪明的人可能已经知道的那样,正确答案是否定的,显然是因为可能存在无限递归。

似乎我只是不明白“在恒定时间内”的含义。我想象的意思,听起来只是意味着一个简单的操作需要已知的时间才能完成。我接受递归可以导致你的程序永远运行,但不是每个操作仍然需要有限且可测量的时间......即使现在有无限数量的它们?或者答案只是意味着不能有效地说两个无限递归程序需要相同的时间来运行?

如果有人能给我“在恒定时间内”的权威定义及其含义,我将不胜感激!

【问题讨论】:

标签: computer-science definition


【解决方案1】:

恒定时间实际上意味着您可以为程序运行所需的时间提供一个恒定的上限,该上限不受任何输入参数的影响。

将其与线性时间(对于某些输入 n - 通常实际上是输入数据的 大小 而不是直接值)进行比较 - 这意味着上限对于mk 的某些值,所花费的时间可以表示为mn + k

请注意,这并不意味着程序会因为任何输入数据在恒定时间内运行而花费相同的时间。例如,考虑这种方法:

int foo(int n)
{
    if (n == 0)
    {
        return 0;
    }
    int j = n + 1;
    int k = j * 2;
    return k;
}

n 为非零的情况下比在它为零的情况下做更多的工作。但是,它仍然是一个常数时间 - 最多,它会进行一次比较、一次加法和一次乘法。

现在将其与递归函数进行比较:

public int foo(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    return n * foo(n - 1);
}

这将递归 n 次 - 所以它在 n 中是线性的。但是,您可能会比线性更糟糕。考虑这种计算斐波那契数的方法:

public int fib(int n)
{
    if (n == 0)
    {
        return 0;
    }
    if (n == 1)
    {
        return 1;
    }
    return fib(n - 2) + fib(n - 1);
}

这并没有看起来比以前的版本差很多 - 但现在是指数(上限最容易用 O(2n)。不过,它仍然只使用简单的比较、加法和函数调用。

【讨论】:

  • 在递归函数中,不应该比较if (n &lt;= 1),因为foo还没有定义吗?
  • 非常感谢 - 谢谢乔恩!
【解决方案2】:

“恒定时间”表示操作将在一定时间(或内存空间 - 这是另一个经常衡量的指标)独立的输入大小中执行。通常你选择一个变量(让我们使用n)来表示输入大小。

O(1) - 恒定时间 - 运行时间不依赖于n

O(n) - 线性时间 - 运行时间n成线性比例

O(n^2) - 二次方时间 - 运行时间n的平方成正比

这些只是几个例子;可能性是无止境。请参阅complexity 上的 wiki 文章

以下是仅由您提到的操作组成的程序可能需要不同时间的几种具体方式:

int n = // some value
doSomething
doSomething
doSomething

注意它的长度是三个something,与n 是什么无关。 O(1)

int n = // some value
def f(n):
    if n == 0 return
    doSomething
    f(n-1)
f(n)

现在我们为每个值 0..n(线性时间,O(n))运行一个 something

我们可以玩得开心-

int n = //some value
def f(n):
    if n == 0 return
    doSomething
    f(n-1)
    f(n-1)

这里的运行时间是多少? (即我们执行了多少something?):)

【讨论】:

  • 谢谢!人们给出的所有非恒定时间函数的例子似乎都是调用自己的函数。是否认为函数接受输入 n,然后在 for 或 while 循环中打印 n 次“Hello”,也不会处于恒定时间(而是线性时间)?
  • 谢谢史蒂文。非常感谢!
【解决方案3】:

“Constant time”与“O(1)”含义相同,并不表示算法运行在固定的时间内,只是表示它不是与输入的长度/大小/大小成正比。也就是说,对于任何输入,它都可以在相同的时间内计算出来(即使那个时间真的很长)。

【讨论】:

    【解决方案4】:

    在“恒定时间”中,通常意味着计算结果所需的时间与输入的大小无关。

    例如。无论列表有多大,在大多数托管语言中计算列表/向量的长度都是在恒定时间内完成的。大小存储为一个单独的字段,并随着列表的增长和缩小而更新。但是计算计数就像读取字段一样简单。

    计算双向链表的大小通常不是常数时间。列表通常可以在两端发生变化,因此没有中心位置来存储计数。因此,确定列表的长度需要访问它并确定其中有多少元素。因此,随着列表的增加,计算答案所需的时间也会增加。

    【讨论】:

    • 假设你没有像LinkedList&lt;T&gt;这样的“容器”对象当然:)
    • @Jon,非常正确。我最近一直在处理没有容器的链表,因此有很多非常量的操作:(
    【解决方案5】:

    “在恒定时间内”意味着无论输入是什么,程序都不会运行超过已知时间。

    考虑阶乘函数作为反例。例如,5 的阶乘计算如下:

    5! = 5 * 4 * 3 * 2 * 1 = 120
    

    与 10 的阶乘相比,这显然需要更少的计算时间,因为要执行后者,程序必须再执行五次乘法:

    10! = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
    

    因此,“恒定时间”并不意味着我们知道程序在每种情况下将运行多长时间,而是它永远不会运行超过已知时间量(上限)。

    【讨论】:

    • 不,它没有。这意味着上限是恒定的,不依赖于输入。某些值的计算结果仍然比其他值更快。
    • 谢谢。我会删除我的评论,但你的评论就没有意义了;)
    • 不,如果它停留在那里表明编程的 Chuck Norris 与我交谈,那完全没问题! :)
    【解决方案6】:

    这里的恒定时间意味着不依赖于输入的数量(而不是输入本身),如果不允许使用 for 或 goto,则使其依赖于输入数量的唯一方法是通过条件和递归。尽管您可能会争辩说,对于一些有争议的解决方案,递归不是必需的。 例如。 (在 C 中)

    if(ReadInput()) DoSomeThing();
    if(ReadInput()) DoSomeThing();
    if(ReadInput()) DoSomeThing();
    if(ReadInput()) DoSomeThing();
    

    【讨论】:

      【解决方案7】:

      要考虑的真正重要的事情是时间如何随着元素数量的变化而变化。 In constant time 意味着无论涉及多少元素,时间都保持不变(外行的解释)。

      【讨论】:

        【解决方案8】:

        如果程序永远运行,那么它不会在已知的时间内完成,因为它没有完成。我们将“恒定时间”的概念应用于整个程序的运行,而不是每个单独的步骤。

        “恒定时间”是指“时间不取决于输入量”。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-05-26
          • 2012-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-27
          • 2010-09-11
          • 1970-01-01
          相关资源
          最近更新 更多