O(n) + O(n) = O(n)?

9 投票
8 回答
11893 浏览
提问于 2025-04-18 12:25

根据Alex Martelli在O'Reilly的《Python in a Nutshell》一书中提到的,复杂度类 O(n) + O(n) = O(n)。所以我相信这个说法,但有点困惑。他解释说,“两个线性函数的和也是一个线性函数。”

根据维基百科的说法,在函数分析中,线性函数是一个线性映射,比如 f(x+y) = f(x) + f(y)。我找到一个似乎更简单的定义,在这里简单地说明,“线性函数是图像是一条直线的函数。”它还包括一些比维基百科上那些看起来更简单的例子。

y = f(x) = a + bx

还有:

y = 25 + 5x

let x = 1
then
y = 25 + 5(1) = 30

let x = 3
then
y = 25 + 5(3) = 40

也许可以合理地期待,两个线性方程的和可以在图上表示为一条直线,这条直线显示出类似于这两条直线的平均值

所以我理解得对吗?即使在下面的两个函数中,“复杂”的函数处理时间是“简单”函数的三倍,但它们在大O表示法中都是O(n),因为处理时间的变化在图上会表现为一条直的斜线,而时间差则体现在图形表示中,复杂函数的角度会更陡峭?

from timer import Timer

def complex(it):
    result = []
    for i in it:
        result.append(i)
    result.reverse()
    return result

def simple(it):
    result = list(it)

longlist = list(range(0, 1000000))

with Timer() as t:
    reverse_(longlist)
print "=> elapsed time reverse: %s." % t.secs

with Timer() as t:
    straight(longlist)
print "=> elapsed time straight: %s" % t.secs

8 个回答

3

假设第一个 O(n) 可以用一个方程表示:

y1 = f1(x) = a1 + b1.x

而第二个 O(n) 也可以用一个方程表示:

y2 = f2(x) = a2 + b2.x

通过把这两个方程的两边相加,

y1 + y2 = f1(x) + f2(x) = (a1+a2) + (b1+b2).x

我们可以看到 y1+y2 也是 O(n)

6

一个好的(也许是最好的)方法是回到大O的数学定义上:

在这里输入图片描述

用简单的话来说:

这两个说法是等价的:

  • fO(g)

  • n 增加时,f(n)g(n) 的比值趋向于一个非负值。

在我们的例子中,g(n) = n。现在如果我们设定 f(n) = f1(n) + f2(n),并假设 f1f2 都是 O(n),那么上面的极限将等于 α = α1 + α2,而这个值必须大于或等于零(因为根据定义 α1 ≥ 0α2 ≥ 0)。因此,f1(n) + f2(n) 也是 O(n),根据我们的定义。

8

所以即使在下面的两个函数中,“复杂”的函数处理时间是“简单”函数的三倍,但它们在大O表示法中都是O(n),因为处理时间的变化在图表上看起来像是一条直线,虽然复杂函数的斜率会更陡一些,对吗?

没错。字母O是用来表示一个函数的“阶”的。线性函数都是同一种,比如O(n)O(3n)O(Cn)都是线性的。

另一方面,O(n^2)O(n^3)O(n^C)都是多项式函数(分别是2次、3次和C次)。在处理算法时,我们通常会开始区分O(n^2)O(n^5)这样的情况,尽管它们都是同一种阶。

O(2^n)O(3^n)O(C^n)则是指数级的。一般来说,你不想写出复杂度是指数级的算法(或者更糟的情况)。

17

没错,O(n) + O(n) = O(n)。

更具体来说,O(n) + O(n) = 2 * O(n),但因为大O符号只关注当函数趋向于无穷大时的表现,所以任何线性的增长都被表示为O(n)。

11

这个说法是对的,因为两个线性函数相加,结果还是一个线性函数。举个例子,看看这两个:

y = 6*x + 10
y = 20*x + 2

把它们加在一起,你会得到:

y = 26*x + 12

这也是一个线性函数!这个道理适用于任何两个线性函数。

y = A*x + B
y = C*x + D
-----------
y = (A+C)*x + (B+D)

撰写回答