7 分钟内理解大 O 符号

2025-06-07

7 分钟内理解大 O 符号

大 O 符号是一个经常被开发人员完全忽略的概念。然而,它却是一个基础概念,不仅实用,而且易于理解。与普遍的看法相反,你不需要成为数学迷就能掌握它。我敢打赌,7 分钟内你就能理解一切。

什么是大 O 符号?

大 O 符号(或算法复杂度)是衡量算法性能的标准方法。它是一种判断代码有效性的数学方法。我之前提到“数学”这个词的时候,把所有人都吓跑了。再说一次,你不需要对数学有热情就能理解和使用这个符号。

这种表示法可以让你测量算法相对于输入数据的增长率。它描述了代码性能的最坏情况。今天我们不讨论空间复杂度,只讨论时间复杂度。

这并不是在函数前后放置一个计时器来查看它需要多长时间。

大 O 符号

问题在于,计时器技术既不可靠也不准确。使用简单的计时器,算法的性能会因多种因素而发生巨大变化。

  • 您的机器和处理器
  • 您使用的语言
  • 运行测试时机器的负载

大 O 符号解决了所有这些问题,并使我们能够可靠地衡量您编写的所有代码的效率。大 O 是“数量级”的简称。

理解这一点至关重要。你不能直接用秒来衡量算法的速度。你应该用完成算法所需的操作数来衡量算法的增长率。在开发人员中衡量性能时,应该使用大 O 符号。

开发人员

不服气?好吧,让我们来想象一下现实生活中的情况!

这可能发生在你身上

想象一下,你正在努力工作,有一天你被要求编写一个函数,返回从 1 到传入参数的数字之间所有数字的和。更确切地说,就是实现这样的行为。

n = 3

output = getSum(n)

print(output)
# will print : 6  because 1 + 2 + 3 = 6
Enter fullscreen mode Exit fullscreen mode

你首先想到的可能是写一个简单的循环,逐个累加这些数字。我会用 Python 给出一些例子,但我们并不关心具体是什么语言。它适用于任何语言。

def getSum(n):
    sum = 0

    for number in range(1, n + 1):
        sum += number

    return sum
Enter fullscreen mode Exit fullscreen mode

果然成功了。你输入 3 启动函数:立刻就得到了正确的结果。太棒了!你正在推送到 prod,然后漫不经心地喝着咖啡。

几天后,有人直接联系你,告诉你系统变得超级慢。这是因为你的函数。你的函数处理时间长达15秒以上!它经常会阻塞整个系统几秒钟。

大 O 符号

慌了!你查看日志,发现输入变成了巨大的数字。有时,你的函数输入会高达 10 亿。不得不让其他开发人员介入。你的函数被替换了,一切恢复正常。你查看新的代码,就看到了。

def getSum(n):
    return n * (n + 1) / 2
Enter fullscreen mode Exit fullscreen mode

这个函数可以立即解决问题,即使输入高达 1 万亿。你在 Slack 上问了实现这个函数的开发者,他的回答让你更加困惑。

你好!你的解法虽然线性趋近于 O(n),但输入量很大。我找到了一个常数解法,时间复杂度为 O(1)。现在,无论输入量有多大,它都会很快。

你看着屏幕,有一个问题让你着迷。

它是如何工作的?

正如我所说,关键在于评估机器需要执行多少次运算才能解决你的问题。对于你的解决方案,需要执行很多运算。

def getSum(n):
    sum = 0  <-- assignment

    for number in range(1, n + 1): <-- addition + range
        sum += number <-- n additions + n assignments

    return sum
Enter fullscreen mode Exit fullscreen mode

我们不会对操作次数进行精确计算,因为我们不在乎具体数字。我们想要根据输入参数得出所需操作次数的趋势。现在最应该令人震惊的是第 4 行和第 5 行的循环。

解决问题所需的运算量将乘以输入的大小。数量级与函数输入的数字 n 直接相关。因此,函数的线性趋势为 O(n)。

输入是10亿?机器需要进行1,000,000,000 * 次运算。

时间

其他功能则不是这样。

def getSum(n):
    return n * (n + 1) / 2 <-- three operations
Enter fullscreen mode Exit fullscreen mode

使用此解决方案,解决问题的运算量不会随着输入的增加而增加。无论输入如何,您的数量级始终是三个运算。因此,您的函数具有 O(3) 的恒定趋势,简化为 O(1)。如果您画一幅图,它看起来就像这样。

大 O 符号

你开始明白为什么记住这个概念很重要了。显然,这种表示法还有其他应用场景。我们来快速看一下。

大 O 符号示例

常数复杂度 O(1)

常数复杂度O(1)无论输入如何变化,每次所需的操作次数都相同。

def exempleO1(n):
    print(n + n)
Enter fullscreen mode Exit fullscreen mode

对数复杂度O(log(n))

如果你不了解数学中对数的概念,那么对数复杂度O(log(n))会更难理解。简而言之,对数趋势与指数趋势相反。指数趋势会随着时间的推移成倍增长,算法的性能也会随之下降,而对数趋势则会呈除法。

def exempleOlogn(n):
    i = 1

    while(i < n):
        i = i * 2
        print(i)
Enter fullscreen mode Exit fullscreen mode

二分查找算法正是根据这一趋势而工作的。

线性复杂度 O(n)

线性复杂度O(n)与输入的大小成正比。运算次数会随着输入数量的增加而增加。最简单的例子是一个简单的循环。

def exempleOn(n):
    for number in range(n):
            print(number + 1)
Enter fullscreen mode Exit fullscreen mode

线性对数复杂度O(n log(n))

线性复杂度O(n log(n))使用与对数复杂度相同的“分而治之”方法,只是它对输入 n 的每个元素都这样做。

def exempleOlogn(n):
    i = 1
    for number in range(n):
        while(i < n):
            i = i * 2
            print(i)
Enter fullscreen mode Exit fullscreen mode

合并排序算法正是顺应了这一趋势。

合并排序算法正是顺应了这一趋势。

二次复杂度 O(n²)

二次复杂度O(n²)将演变为输入的平方。运算次数也将增长到输入的平方。两个嵌套循环就是这种趋势的完美例证。

def exempleOn2(n):
    for number in range(n):
        for number in range(n):
            print(number + 1)
Enter fullscreen mode Exit fullscreen mode

最著名的排序算法(快速排序冒泡排序插入排序)都有这种趋势。

还有很多其他的我就不说了。如果你想全部看完,维基百科页面很有意思。

大 O 符号

另外,看看这个简短的 YouTube 视频,它对理解简化符号书写的规则非常有用。例如,为什么 O(3) 简化为 O(1)?为什么两个非嵌套循环的复杂度仍然是 O(n)?就像你的专业领域中的任何学科一样,它涉及知识的海洋。

海洋

最后,我们将讨论为什么这一切都很重要。

为什么这很重要?

我看到一些开发人员使用小批量软件,确信这些对他们毫无用处。甚至一些拥有300年经验的开发人员也不需要这些东西。

大 O 符号快速解答了每个开发人员在工作中都应该问自己的一个问题:我的解决方案的扩展性如何?无论你的数据量是否巨大,这都无关紧要。重要的是,你必须了解解决方案的极限,以便估算系统的极限。

然后,通过理解这个概念,你将拥有一种与其他开发人员讨论的标准语言。这对于比较解决方案、做出权衡以及简单地交换技术信息都很重要。

如果你不明白我们在说什么,那你就有障碍了。就我个人而言,在我职业生涯初期的采访中也遇到过这种情况。我完全不知道他在说什么,当时我非常恐慌。

大 O 符号

有了这些基本的理解,我解决问题的方式就改变了。作为一名开发人员,编写优化的代码至关重要。

最后但同样重要的是,这些概念能让你快速发现运行缓慢的系统出了什么问题。很多时间都花在阅读和修复其他开发人员的代码上。所有这些都能让你更快地找到并优化运行缓慢的代码。

结语

我希望这篇关于大 O 符号的介绍能让你了解更多信息。了解这个概念对于更好地优化你的代码至关重要。总的来说,随着你的职业生涯发展,它会对你越来越有用。

文章来源:https://dev.to/jesuisundev/understand-big-o-notation-in-7-minutes-gp9
PREV
5分钟了解VueJS
NEXT
有人盗用了我的 DEV 文章!如何编写 Python 脚本检测被盗内容?编写 Python 脚本检测是否有人盗用了你的 DEV 文章?