【问题标题】:Triple nested while loop - Big Oh Notation - Count of Primitive Operations三重嵌套while循环 - 大哦符号 - 原始操作计数
【发布时间】:2022-09-28 04:14:23
【问题描述】:

我在确定以下代码行的原始操作计数时遇到了一些麻烦

def question1(n):
    n = n           # 1 ops
    i = 0           # 1 ops
    a = 0           # 1 ops
    while i < n:            # n ops
        j = 0               # n ops
        while j < n:        # n * n ops
            k = 0           # n * n ops
            while k < 60:                   # n * n * 60 ops
                a = i * j - i * 2 + k       # n * n * 60 * 5 ops
                k += 1                      # n * n * 60 * 2 ops
            j += 1          # n * n ops
        i += 1              # n ops

# total sum of prim operations = (n * n * 483) + (3 * n) + 3

我不确定是否

            while k < 60:                   # n * n * 60 ops
                a = i * j - i * 2 + k       # n * n * 60 * 5 ops
                k += 1                      # n * n * 60 * 2 ops

真的吗

n * n * 60?

或者应该是

 n * n * n * 60
  • 最里面的循环应该被视为O(1) 操作(如果所有二进制操作都被视为O(1) 操作)。
  • 大 O 的全部意义在于忽略乘法常数(以及非显性项),因此 O(60*n^k) 与 O(n^k) 相同。
  • 如果我们忽略常量,这应该是 O(n^3) 还是 O(n^2) ?我听到了不同的答案,我很困惑
  • 你的表达式中没有n^3,那为什么应该是n^3呢?
  • 我认为 Big Oh 表示法是 O(n^3),因为有三个 while 循环,但人们说最内层循环不计在内,因为它是常数,所以 Big Oh 是 O(n^2)

标签: python algorithm time time-complexity big-o


【解决方案1】:

“原始操作”是一个模棱两可的概念。例如,while 语句将在某些时候将条件评估为 false(您没有计算在内),然后执行跳转到语句循环。可以说这是两个操作(评估+跳转)。

有人可能会说k += 1 应该算作 3 次操作:

  • k的值加载到CPU寄存器中,
  • 添加一个
  • 将该寄存器的值存储回k

但是,如果将 Python 编译成具有 INC 指令的机器语言(如 NASM),并且我们处理固定大小的整数(如 32 位),则它只是一个操作。

所以这个概念是模糊的,总结起来也没什么用。您不应识别“原始操作”,而应识别具有恒定时间复杂度的代码块。

常数时间复杂度分析

首先,我们需要决定是否将整数算术运算考虑为constant in time,或者我们是否应该考虑整数(当然在 Python 中)可以具有任意大小,因此这些运算可以进行not have a constant time complexity。另见"bit complexity"。我在这里假设您希望将算术运算视为具有恒定的时间复杂度。

然后我们可以确定这段代码具有恒定的时间复杂度:

            k = 0
            while k < 60:
                a = i * j - i * 2 + k
                k += 1
            j += 1

请注意,执行内部块(具有恒定复杂度)60 次,仍然意味着总数具有恒定的时间复杂度,因为 60 是一个常数(与输入无关)。

此外,整数变量的初始化或它们的递增都表示恒定的时间复杂度。

有两个嵌套循环,每个循环在执行时迭代 ? 次。所以这意味着(上面的)内部部分被执行了?²次。

因此,整体时间复杂度为 O(?²)

【讨论】:

    【解决方案2】:

    我会说它绝对不是 n * n * n * 60。你可能会对渐近符号感到困惑,这可能首先会影响这个问题。第三个 while 循环执行了 60 次,这意味着其中的每个操作都执行了 60 次。对于第二个 while 循环的 n 次迭代,该 while 循环每次运行 60 次,对于第一个 while 循环的 n 次迭代,每次运行 n 次,产生 n * n * 60。

    虽然这里涉及到 60,但它仍然是一个常数,因此对于较大的 n 值意义不大。在这种情况下,使用三重嵌套循环更像是一个技巧问题,旨在展示一个示例,说明为什么算法的多项式属性比任何常数都更重要,因为随着 n 变大,n * n 变得更大超过60。

    不过,您的计算看起来是正确的。唯一错过的是以下块实际上是每个 2 个操作:

    j += 1          # n * n * 2 ops, equal to j = j + 1, an assignment AND addition
    i += 1          # n * 2 ops ( i = i + 1 )   
    

    【讨论】:

    • 你完全正确,我最后忽略了这些操作。
    • 那么你会说这个算法的大 O 表示法是 O(n^2) 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多