大O,你是如何计算/近似的?

2023-11-24

大多数拥有计算机科学学位的人肯定知道什么大O代表。 它帮助我们衡量算法的扩展程度。

但我很好奇,怎么办you计算或近似算法的复杂性?


我将尽力在这里用简单的术语解释它,但请注意,这个主题需要我的学生几个月的时间才能最终掌握。您可以在第 2 章中找到更多信息Java 中的数据结构和算法 book.


没有机械程序可以用来获得 BigOh。

作为一本“食谱”,获得BigOh从一段代码中,您首先需要意识到您正在创建一个数学公式来计算给定一定大小的输入执行的计算步骤。

目的很简单:从理论角度比较算法,而不需要执行代码。步骤数越少,算法越快。

例如,假设您有这段代码:

int sum(int* data, int N) {
    int result = 0;               // 1

    for (int i = 0; i < N; i++) { // 2
        result += data[i];        // 3
    }

    return result;                // 4
}

该函数返回数组所有元素的总和,我们想要创建一个公式来计算计算复杂度该函数的:

Number_Of_Steps = f(N)

所以我们有f(N),一个计算计算步骤数的函数。函数的输入是要处理的结构的大小。这意味着该函数被调用,例如:

Number_Of_Steps = f(data.length)

参数N采取data.length价值。现在我们需要函数的实际定义f()。这是通过源代码完成的,其中每个有趣的行都从 1 到 4 编号。

计算 BigOh 的方法有很多种。从现在开始,我们将假设每个不依赖于输入数据大小的句子都采用一个常数C计算步骤数。

我们将添加函数的单独步数,局部变量声明和返回语句都不依赖于函数的大小data array.

这意味着第 1 行和第 4 行各需要 C 个步骤,函数有点像这样:

f(N) = C + ??? + C

下一部分是定义的值for陈述。请记住,我们正在计算计算步骤的数量,这意味着for语句被执行N次。这与添加相同C, N times:

f(N) = C + (C + C + ... + C) + C = C + N * C + C

没有机械规则来计算身体的次数for被执行后,你需要通过查看代码做了什么来计算它。为了简化计算,我们忽略变量初始化、条件和增量部分for陈述。

为了获得真正的 BigOh,我们需要渐近分析的函数。这大致是这样完成的:

  1. 去掉所有常数C.
  2. From f()得到多项式 in its standard form.
  3. 将多项式的项相除并按增长率排序。
  4. 保留长大的那个N方法infinity.

Our f()有两个术语:

f(N) = 2 * C * N ^ 0 + 1 * C * N ^ 1

带走所有的C常量和冗余部分:

f(N) = 1 + N ^ 1

由于最后一项在以下情况下会变得更大:f()接近无穷大(思考limits)这是 BigOh 论证,并且sum()函数的 BigOh 为:

O(N)

有一些技巧可以解决一些棘手的问题:使用总结随时你可以。

例如,可以使用求和轻松解决此代码:

for (i = 0; i < 2*n; i += 2) {  // 1
    for (j=n; j > i; j--) {     // 2
        foo();                  // 3
    }
}

您需要问的第一件事是执行顺序foo()。虽然通常是O(1),你需要询问你的教授。O(1)意味着(几乎,大部分)恒定C,与尺寸无关N.

The for关于第一句话的陈述很棘手。虽然索引结束于2 * N,增量为 2。这意味着第一个for仅被执行N步骤,我们需要将计数除以二。

f(N) = Summation(i from 1 to 2 * N / 2)( ... ) = 
     = Summation(i from 1 to N)( ... )

句子编号two甚至更棘手,因为它取决于i。看一下:索引 i 的值为:0, 2, 4, 6, 8, ..., 2 * N,第二个for执行:第一个阶段 N 次,第二个阶段 N - 2 次,第三个阶段 N - 4 次...直到 N / 2 阶段,第二个阶段for永远不会被处决。

根据公式,这意味着:

f(N) = Summation(i from 1 to N)( Summation(j = ???)(  ) )

我们再次数数步数。根据定义,每个求和都应始终从 1 开始,并以大于或等于 1 的数字结束。

f(N) = Summation(i from 1 to N)( Summation(j = 1 to (N - (i - 1) * 2)( C ) )

(我们假设foo() is O(1)并采取C steps.)

我们这里有一个问题:当i取值N / 2 + 1向上,内部求和以负数结束!这是不可能的,也是错误的。我们需要将求和一分为二,作为此刻的关键点i takes N / 2 + 1.

f(N) = Summation(i from 1 to N / 2)( Summation(j = 1 to (N - (i - 1) * 2)) * ( C ) ) + Summation(i from 1 to N / 2) * ( C )

自从关键时刻i > N / 2,内部for不会被执行,并且我们假设其主体具有恒定的 C 执行复杂度。

现在可以使用一些恒等规则来简化求和:

  1. 求和(w 从 1 到 N)( C ) = N * C
  2. 求和(w 从 1 到 N)( A (+/-) B ) = 求和(w 从 1 到 N)( A ) (+/-) 求和(w 从 1 到 N)( B )
  3. 求和(w 从 1 到 N)( w * C ) = C * 求和(w 从 1 到 N)( w ) (C 是一个常数,独立于w)
  4. 求和(w 从 1 到 N)( w ) = (N * (N + 1)) / 2

应用一些代数:

f(N) = Summation(i from 1 to N / 2)( (N - (i - 1) * 2) * ( C ) ) + (N / 2)( C )

f(N) = C * Summation(i from 1 to N / 2)( (N - (i - 1) * 2)) + (N / 2)( C )

f(N) = C * (Summation(i from 1 to N / 2)( N ) - Summation(i from 1 to N / 2)( (i - 1) * 2)) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - 2 * Summation(i from 1 to N / 2)( i - 1 )) + (N / 2)( C )

=> Summation(i from 1 to N / 2)( i - 1 ) = Summation(i from 1 to N / 2 - 1)( i )

f(N) = C * (( N ^ 2 / 2 ) - 2 * Summation(i from 1 to N / 2 - 1)( i )) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - 2 * ( (N / 2 - 1) * (N / 2 - 1 + 1) / 2) ) + (N / 2)( C )

=> (N / 2 - 1) * (N / 2 - 1 + 1) / 2 = 

   (N / 2 - 1) * (N / 2) / 2 = 

   ((N ^ 2 / 4) - (N / 2)) / 2 = 

   (N ^ 2 / 8) - (N / 4)

f(N) = C * (( N ^ 2 / 2 ) - 2 * ( (N ^ 2 / 8) - (N / 4) )) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - ( (N ^ 2 / 4) - (N / 2) )) + (N / 2)( C )

f(N) = C * (( N ^ 2 / 2 ) - (N ^ 2 / 4) + (N / 2)) + (N / 2)( C )

f(N) = C * ( N ^ 2 / 4 ) + C * (N / 2) + C * (N / 2)

f(N) = C * ( N ^ 2 / 4 ) + 2 * C * (N / 2)

f(N) = C * ( N ^ 2 / 4 ) + C * N

f(N) = C * 1/4 * N ^ 2 + C * N

BigOh 是:

O(N²)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大O,你是如何计算/近似的? 的相关文章

  • 定点数学比浮点运算快吗?

    多年前 即 20 世纪 90 年代初期 我构建了图形软件包 该软件包基于定点算术和预先计算的 cos sin 表格以及使用牛顿近似方法进行 sqrt 和对数近似的缩放方程来优化计算 这些先进技术似乎已经成为图形和内置数学处理器的一部分 大约
  • 计算 [1..N] 中前导 1 下面有 K 个零位的整数? (没有 HW POPCNT 的连续范围的 popcount)

    I have following task Count how many numbers between 1 and N will have exactly K zero non leading bits e g 710 1112 will
  • Python Pandas:沿一列比较两个数据帧,并返回另一个数据帧中两个数据帧的行内容

    我正在处理两个 csv 文件并作为数据框 df1 和 df2 导入 df1 有 50000 行 df2 有 150000 行 我想将 df2 的 时间 与 df1 求时间差并返回所有列的值 对应相似的行 保存在df3中 时间同步 例如 35
  • 非阻塞方法中的饥饿

    一段时间以来 我一直在阅读有关非阻塞方法的内容 这是一段所谓的无锁计数器的代码 public class CasCounter private SimulatedCAS value public int getValue return va
  • 在任意时间范围内找到最佳日/月/年间隔的算法?

    如果您有时间表 请说 March 19 2009 July 15 2011 是否有一种算法可以将该时间范围分解为 March 19 2009 March 31 2009 complete days April 1 2009 December
  • iOS 自定义单元格设计放在哪里? awakeFromNib 还是 cellForRowAtIndexPath?

    所以 基本上我用笔尖做了一个定制单元 希望我应用一些定制设计 比如颜色和阴影 我发现了两种应用样式的方法 awakeFromNib override func awakeFromNib super awakeFromNib Containe
  • 对于双核手机,availableProcessors() 返回 1

    我最近购买了一部 Moto Atrix 2 手机 当我尝试查看手机中的处理器规格时 Runtime getRuntime availableProcessors 返回 1 proc cpuinfo 也仅包含有关处理器 0 的信息 出于好奇
  • 有效积累稀疏 scipy 矩阵的集合

    我有一个 O N NxN 的集合scipy sparse csr matrix 每个稀疏矩阵都有 N 个元素集 我想将所有这些矩阵加在一起以获得一个常规的 NxN numpy 数组 N 约为 1000 矩阵内非零元素的排列使得所得总和肯定不
  • 使用实际值检查 cvxpy 中的约束是否正确

    在 cvxpy 中解决优化问题时 是否有一种好方法可以通过用实际值替换优化变量来检查约束是否有效 我有一个复杂的优化问题 100 多个约束 但我知道最佳解决方案应该是什么 但是 cvxpy 失败并显示错误消息ValueError Rank
  • LRU算法,实现这个算法需要多少位?

    我有一个关于 LRU 算法的小问题 如果您有一个包含四个块的高速缓存 那么需要多少位来实现该算法 假设您指的是 4 路组关联缓存 完美 LRU 本质上是按照使用顺序为每一行分配一个精确的索引 您也可以将其视为 年龄 因此 4 个元素中的每一
  • Python 旅行商贪婪算法 [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 因此 我为旅行推销员问题创建了一种排序 并按 x 坐标和 y 坐标进行排序 我正在尝试实施贪婪搜索 但无法做到 此外 每
  • 在Python列表中交换元素的最快方法

    在Python中交换两个列表元素是否有比 L a L b L b L a 或者我必须求助于Cython http cython org or Weave http www scipy org Weave或类似的 看起来 Python 编译器
  • 重写修改后的 goto 语义的算法

    我有一大堆使用旧的自行设计的脚本语言编写的遗留代码 我们将它们编译 翻译成 javascript 该语言有条件跳转 跳转到标签 与普通 goto 语句的区别在于 不可能向后跳转 该语言中没有嵌套的 if 语句或循环 由于 javascrip
  • 这个函数(for循环)空间复杂度是O(1)还是O(n)?

    public void check 10 for string i list Integer a hashtable get i if a gt 10 hashtable remove i 这是 O 1 还是 O n 我猜测 O n 但不是
  • 我应该对算法使用递归还是记忆化?

    如果我可以选择使用递归或记忆来解决问题 我应该使用哪一个 换句话说 如果它们都是可行的解决方案 因为它们提供了正确的输出并且可以在我正在使用的代码中合理地表达 那么我什么时候会使用其中一个而不是另一个 它们并不相互排斥 您可以同时使用它们
  • 为什么这个算法的Big-O复杂度是O(n^2)?

    我知道这个算法的大O复杂度是O n 2 但我不明白为什么 int sum 0 int i 1 j n n while i lt j sum 即使我们设定了j n n一开始 我们在每次迭代期间递增 i 并递减 j 因此最终的迭代次数不应该比n
  • Java 11 中使用堆栈跟踪的速度明显慢于 Java 8

    我正在比较 JDK 8 和 11 的性能jmh https openjdk java net projects code tools jmh 1 21 当我遇到一些令人惊讶的数字时 Java version 1 8 0 192 vendor
  • 是否可以提高 Mongoexport 速度?

    我有一个 1 3 亿行的 MongoDB 3 6 2 0 集合 它有几个简单的字段和 2 个带有嵌套 JSON 文档的字段 数据以压缩格式 zlib 存储 我需要尽快将其中一个嵌入字段导出为 JSON 格式 然而 mongoexport 需
  • 优化视图状态

    是否有人对优化 ASP NET 应用程序的视图状态有任何想法或参考可以向我指出 我不想把它全部关闭 优化它的主要目标是提高性能 所以我不想运行一个昂贵的函数来递归地禁用某些控件的视图状态 因为该函数会减慢速度页面的加载时间会达不到目的 有任
  • 在一个区域中拟合二维多边形的算法?

    这有标准吗 算法名称 说 我有 10 个不同大小的多边形 我有一个特定大小的区域 我想知道如何填充该区域中的最多多边形 以及它们是如何拟合的 笔记 多边形可以根据限制集进行旋转 一个可能的名称是包装问题 http en wikipedia

随机推荐

  • 如何突出显示基于当前页面的链接?

    抱歉 如果这听起来像是一个非常愚蠢的问题 但当您位于链接到的页面上时 我需要使链接改变颜色 例如 当您访问 StackOverflow 的 问题 页面时 顶部的链接会改变颜色 你怎么做到这一点 这是服务器端的事情 在渲染页面时 向链接添加一
  • System.ObjectDisposeException:无法访问关闭的流

    这是否确实意味着该流已被代码处置 无论是在 using 中还是通过调用 dispose 流可能已在此代码之外关闭 并且此异常仍然会发生 所以我将以我的评论作为答案 是的 流也可以从代码外部关闭 所以请确保检查System ObjectDis
  • 求0、2、4、6、8组成的递增数列中的第n个数?

    我们有一个递增序列 其中每个元素仅由偶数组成 0 2 4 6 8 我们怎样才能find the nth number in this sequence 是否有可能在 O 1 时间内找到该序列中的第 n 个数字 顺序 0 2 4 6 8 20
  • 在Rcpp中实现apply函数

    我一直在尝试在 Rcpp 中实现 apply 函数 到目前为止代码如下所示 Rcpp export NumericVector apply NumericMatrix x int dim Function f NumericVector o
  • 在 C 语言中,声明指针的正确语法是什么?

    我依稀记得之前在另一个问题的回答中看到过这个 但搜索并没有找到答案 我不记得是什么了proper声明变量为指针的方法 是吗 Type instance Or Type instance 尽管我知道两者在大多数情况下都会编译 但我相信在某些示
  • false' 在 maven 3' aria-label=''false' 在 maven 3'> 'false' 在 maven 3

    为什么 maven 3 在 pom xml 的快照存储库配置中贬值 false 其背后的动机是什么
  • 从应用程序注销后如何取消订阅 FCM 通知?

    我已经在我的应用程序中实现了 Firebase 云消息传递以用于推送通知 一切工作正常 但即使用户从应用程序注销 也会收到通知 我听说 当用户从应用程序注销时 我需要删除 FCM 令牌 所以我在注销方法中这样做了 void logout F
  • 如何为vim设置syntastic?

    所以我将存储库克隆到 vim bundle并安装了病原体 我可以确定病原体工作正常 因为我的捆绑包中的其他插件都工作正常 经过谷歌搜索一段时间后 似乎 syntastic 应该可以直接用于 c 代码 我还检查了我是否拥有指定的所有可执行文件
  • T-SQL - 什么是内联视图?

    我最近回答了这个问题如何按顺序调用用户定义的函数以与按顺序选择组一起使用 我的答案是使用内联视图来执行该功能 然后对其进行分组 在评论中 提问者没有理解我的回答 并要求提供一些网站 参考资料来帮助解释 我快速谷歌了一下 没有找到任何很好的资
  • 在 Swift 中使用 NumberFormatter 格式化大十进制数

    我这样做是为了格式化数字 但对于大数字来说失败 let formatter NumberFormatter formatter numberStyle decimal if let number formatter number from
  • 在 Eclipse 中使用 Gwt 2.7

    有gwt 2 7版本的eclipse插件吗 如果我从官方存储库安装 eclipse 插件 https dl google com eclipse plugin 4 4 它将 Google Web Toolkit SDK 2 6 0 列为唯一
  • 调整图像大小以适合 div

    如何调整图像大小以适合 div 的大小piecemaker container div div img src splash jpg alt some text div div piecemaker container display bl
  • 选择性同步 Google Drive 本地文件夹? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 Google Drive 中是否有一种方法可以对本地文件夹进行选择性同步 即将父文件夹同步到云 同时仅将某些选定的子文件夹保留在本地 例如 在我的本地电脑上project文件夹有3个
  • 搜索 ClearCase 来查找带有特定评论的签入

    我被要求提供大约 3 个月前签入 ClearCase 的详细信息 我知道评论中包含的 QC 编号 但迄今为止完全未能找到一种方法来搜索 ClearCase 以通过评论签入 有任何想法吗 布赖恩 阿格纽走在正确的轨道上 但需要注意的是 我确信
  • Conda:直接从 github 安装/升级

    我可以使用以下命令从 GitHub 安装 升级包吗conda 例如 与pip我可以 pip install git git github com scrappy scrappy master 安装scrappy直接从masterGitHub
  • python 中导入 timeit.timeit 变量

    我正在尝试使用timeit timeit 以便找出执行特定代码行需要多少时间 问题是这一行包含变量 我需要以某种方式导入它们 所以我的问题是如何导入 为了更清楚 代码看起来像这样 def func var1 aaa var2 aab t1
  • Android:使用 FLAG_SECURE 时更改窗口背景的颜色

    我有一个请求 当我的 Android 应用程序放入后台时 我会清空屏幕以隐藏敏感数据 使用以下方法很容易实现 getWindow addFlags WindowManager LayoutParams FLAG SECURE 困难的部分似乎
  • Python 如何比较“int”和“float”对象?

    文档关于数字类型指出 Python 完全支持混合算术 当二元算术运算符具有不同数值类型的操作数时 较窄 类型的操作数会扩展到另一个操作数 其中整数比浮点窄 浮点又比复数窄 混合类型的数字之间的比较使用相同的规则 以下行为支持这一点 gt g
  • Rails 5 - 对象关系阻抗以及如何构造多个继承的类/表

    EDIT我对原文进行了编辑 以便更容易理解 我了解对象关系阻抗问题 我了解 Rails STI 和多态性 Rails 方式 但它不是真正的 OO 多态性 我已经阅读了大量有关此问题的博客和问题 但仍然找不到这个问题的答案 class Per
  • 大O,你是如何计算/近似的?

    大多数拥有计算机科学学位的人肯定知道什么大O代表 它帮助我们衡量算法的扩展程度 但我很好奇 怎么办you计算或近似算法的复杂性 我将尽力在这里用简单的术语解释它 但请注意 这个主题需要我的学生几个月的时间才能最终掌握 您可以在第 2 章中找