微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将算法从 O(2N) 优化到 O(N) 会使其速度提高一倍吗?

如何解决将算法从 O(2N) 优化到 O(N) 会使其速度提高一倍吗?

在 Big-O Notation 中,O(N) 和 O(2N) 描述了相同的复杂性。也就是说,一个算法在 O(2N) 的时间或空间复杂度的增长速度本质上等于 O(N)。与复杂度为 O(N^2) 的算法相比,给定 N 的极大值时,尤其可以看出这一点。O(N) 线性增加,而 O(N^2) 二次增加

所以我理解为什么 O(N) 和 O(2N) 被认为是相等的,但我仍然不确定是否将这两者视为完全相等。在输入数量 N 为 100 万或更多的程序中,在我看来,将时间复杂度减半实际上会节省相当多的时间,因为该程序可能会少执行数百万个操作。

我正在考虑一个包含两个 for 循环的程序。每个 for 循环在一个非常大的 N 元素数组的整个长度上迭代。该程序的复杂度为 O(2N)。 O(2N) 减少到 O(N),但我觉得只需要一个 for 循环而不是两个的实现会使程序更快(即使单个 for 循环实现为了速度而牺牲了一些功能) ,例如)。

我的问题:

如果你有一个时间复杂度为 O(2N) 的算法,将其优化为 O(N) 时间复杂度会使其速度提高一倍吗?

换句话说,将 O(2N) 算法优化为 O(N) 是否有显着益处?我想程序的速度会有所提高,还是会因为 O(2N) == O(N) 而增加微不足道以至于不值得付出努力?

解决方法

时间复杂度与速度不同。对于给定的数据大小,带有 O(N) 的程序可能比 O(2N) 更慢、更快或速度相同。此外,对于给定的数据大小,O(N) 可能比 O(N^2) 更慢、更快或相同。

所以如果 Big-O 没有任何意义,我们为什么还要谈论它?

Big-O 表示法描述了程序随着数据大小增加的行为。这种行为总是相对。换句话说,Big-O 告诉您渐近曲线的形状,而不是它的尺度或维度。

假设您有一个 O(N) 的程序 A。这意味着处理时间将与数据大小成线性比例(忽略可能使运行时间更像分段线性的缓存大小等现实世界的复杂性):

  • 1000 行需要 3 秒
  • 2000 行需要 6 秒
  • 3000 行需要 9 秒

对于另一个也是 O(N) 的程序 B:

  • 1000 行需要 1 秒
  • 2000 行需要 2 秒
  • 3000 行需要 3 秒

显然,第二个程序每行快 3 倍,即使它们都有 O(N)。直观地说,这告诉您两个程序都会遍历每一行并花费一些固定的时间来处理它。从 2000 年到 1000 年的时间差异与从 3000 年到 2000 年的差异相同 - 这意味着增长线性,换句话说,一条记录所需的时间不取决于所有记录的数量记录。这相当于程序执行某种 for 循环,例如在计算数字总和时。

而且,由于程序不同并且做不同的事情,因此将程序 A 的 1 秒时间与程序 B 的 1 秒时间进行比较是没有任何意义的。你会比较苹果和橙子。这就是为什么我们不关心常数因子,我们说 O(3n) 等价于 O(n)

现在想象第三个程序 C,它是 O(N^2)

  • 1000 行需要 1 秒
  • 2000 行需要 4 秒
  • 3000 行需要 9 秒

这里 3000 年和 2000 年的时间差比 2000 年和 1000 年的差要大。数据越多,增幅越大。这相当于程序在 for 循环内执行 for 循环 - 例如在数据中搜索对时。

当您的数据较小时,您可能不会在意 1-2 秒的差异。如果您仅根据上述时间比较程序 A 和 C,并且不了解潜在行为,您可能会说 A 更快。但是看看更多记录会发生什么:

  • 对于 10000 行程序 A 将需要 30 秒
  • 对于 10000 行程序 C 将需要 1000 秒
  • 对于 20000 行程序 A 将需要 60 秒
  • 对于 20000 行程序 C 将需要 4000 秒

对于相同的数据,最初的相同性能很快变得非常明显 - 几乎是 100 倍。在这个世界上,没有办法在更快的 CPU 上运行 C 如何跟上 A,而且数据越大,这越是真实。使一切变得不同的是可扩展性。这意味着要回答诸如当数据库增长到两倍于其大小的 1 年内我们需要多大的机器这样的问题。使用 O(N),您通常没问题 - 您可以购买更多服务器、更多内存、使用复制等。使用 O(N^2) 您通常可以在达到一定规模时购买任意数量的新机器将不足以解决您的问题,您将需要在软件中找到不同的方法,或者在 GPU 集群等大规模并行硬件上运行它。使用 O(2^N) 除非您能以某种方式将数据的最大大小限制为仍然可用的内容,否则您几乎完蛋了。

请注意,以上示例是理论上的,并且是有意简化的;正如@PeterCordes 指出的那样,由于缓存、分支预测错误、数据对齐问题、向量操作和数百万其他特定于实现的细节,真实 CPU 上的时间可能会有所不同。请在下面的评论中查看他的链接。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。