算法分析

概念:算法分析是关于计算机程序性能和资源利用的理论研究。主要关注点在于程序性能,如何让程序运行的更快。同时也会涉及其他问题,例如通信,存储器等。

问题1:什么比性能更重要?

正确性,可维护性,简洁性,程序员的时间成本,健壮性,功能性,模块化,安全性,可扩展性,用户友好性等等

问题2:如果算法和性能和都不重要,为什么还要学习它们?

  1. 算法能够将不可行变成可行
    如:在实时需求中,程序不够快等同于不可行;如果程序占用过多的内存,也是不可行的。

  2. 算法已经成为一种广泛应用于计算机科学领域的描述程序行为的语言。

  3. 性能处于最底层,其角色和经济中的货币相似,就像你可以用货币买来水(水对你的生命来说比货币更重要),你也可以“支付”性能来换取良好的用户体验,或换取安全性。
    一个例子:有人希望有更多的功能,因此用Java来写程序,尽管它比C写的程序慢的多(可能会损失三倍的性能),但考虑到Java的优点(面向对象,异常处理等),人们愿意“支付”三倍性能。

  4. 算法很有趣

下面以排序问题为例引入算法分析。

问题描述:一组输入序列<a1,a2,...an><script type="math/tex" id="MathJax-Element-1"></script>,按照需求重新排列后输出<a′1,a′2,...a′n><script type="math/tex" id="MathJax-Element-2"></script>
满足a′1⩽a′2⩽...⩽a′na_1' \leqslant a_2' \leqslant ...\leqslant a_n'

插入排序

伪代码

与编程语言很类似,只是经常包含一些英语,能够让我们更容易理解算法所要表达的意思。

插入排序伪代码:

Insertion-Sort(A, n) // Sorts A[1...n]
for j ← 2 to ndo key ← A[j]i ← j-1while i > 0 and A[i] > keydo A[i+1] <- A[i]i ← i-1A[i+1] ← key

伪代码解析:
A为待排序的数组。在外层for循环中,j从2递增到n,在算法任意一步,取出数组A中的第j个值(之前的部分已经有序),把这个值存在key中,并依次把前一个元素向后移一位,直到前一个元素不大于key为止,从而让“有序”的部分长度增加1。如下图所示:

举例:
给定数组 8,2,4,9,3,6,并设定j从2开始(即从第二个元素“2”开始)
排序过程如下:

算法运行时间:

  1. 与输入本身有关(假如输入已经有序,则运行时间将会很短)
  2. 与输入规模有关(上面的例子输入规模为6,如果变为6×1096\times10^9,运行时间将会变长)
    ——我们将把运行时间看成是输入规模的函数
  3. 我们想知道运行时间的上限

算法分析的种类:

  • 最坏情况分析(最经常用到)
    T(n)T(n) = 输入规模为n时算法的最长运行时间

  • 平均情况分析(有时用到)
    T(n)T(n) = 输入规模为n时算法的期望运行时间
    期望运行时间 = 所有输入按概率加权平均的运行时间
    每种输入出现的概率是未知的,所以要先假设每种输入出现的概率分布

  • 最好情况分析(假象)
    可以给慢速算法选择特定的输入,从而使运行时间很短,但是,这种信息没什么用。

问题:插入排序算法的最坏情况运行时间是多少?

思考:
算法的运行时间与计算机的配置有关(超级计算机?腕表计算机?)
——“相对运行时间”(不同算法在同一台计算机上运行的时间)
——“绝对运行时间”(有没有一种算法在任何计算机上运行时间都很短?)
当讨论软件相关的算法的最坏运行时间而不涉及硬件时,会造成困惑。

如何解决这种复杂的局面?如何把问题简化到可以用数学手段来处理?
那就是“大局观”——渐近分析

渐近分析

  1. 忽略掉那些依赖于机器的常量
  2. 关注运行时间的增长性(而不是实际运行时间)T(n):n→∞T(n) :n \rightarrow \infty

为了更好的解释渐近分析,首先引入渐近符号:
Θ\Theta:丢掉低阶项,并忽略前面的常数因子
例:3x3+90n2−5n+6046=Θ(n3)3x^3 + 90n^2 - 5n + 6046 = \Theta(n^3)
因此我们知道,当n →∞\rightarrow \infty时,Θ(n2)\Theta(n^2)的算法总比Θ(n3)\Theta(n^3)的算法快,即使在较慢的计算机上运行Θ(n2)\Theta(n^2)的算法,在较快的计算机上运行Θ(n3)\Theta(n^3)的算法,这个性质仍然满足。因为不同的平台上我们可能只差一个常数因子。

下图展示了Θ(n3)\Theta(n^3)的算法与Θ(n2)\Theta(n^2)的算法运行时间与输入规模的关系。

可以看出,总有一个点n0n_0,当输入规模大于n0n_0时,Θ(n2)\Theta(n^2)的算法都比Θ(n3)\Theta(n^3)的算法有更小的开销。
然而,从工程的角度来看,仍存在一个问题:有时n0n_0太大了,大到计算机无法运行这样的算法,因此我们有时也对低速算法感兴趣。尽管从渐近的观点来看它们的运行速度比较慢,但它们在合理规模的输入下运行得更快。
结论:要在数学理解与工程直觉之间做出权衡(仅仅会做算法分析是不够的,还需要学习怎样编程以及在实践中运用这些工具)

插入排序算法分析

最坏情况:输入序列为逆序
进行操作数目计数的一种方法:内存引用计数(实际上访问了某个变量多少次)
T(n)=∑nj=2Θ(j)=Θ(n2)T(n) = \sum_{j=2}^{n}\Theta(j) = \Theta(n^2)  (算数级数)

插入排序快吗?

如果输入规模很小,比较快
如果输入规模很大,并不快

下面引入一个更快的排序方法,归并排序。

归并排序

算法步骤包括以下3点:
1. 如果n = 1,排序完毕
2. 递归排序A[1,⌈n/2⌉]A[1, \lceil n/2 \rceil]和A[⌈n/2⌉+1,n]A[\lceil n/2 \rceil + 1, n]
3. 合并两个排好序的序列

关键的子程序:归并

假设现在已经有两个有序的子序列
A[1,⌈n/2⌉]A[1, \lceil n/2 \rceil]:2,7,13,20
A[⌈n/2⌉+1,n]A[\lceil n/2 \rceil + 1, n]:1,9,11,12
想要将这两个序列合并成一个大的目标序列,具体做法如下:
1. 找出两个序列中最小值,作为目标序列的第一个值,并将这个最小值从原序列中“划掉”
由于两序列都已经有序,因此最小值只能是第一个序列或第二个序列的第一个值,比较“1”和“2”,”选择“1”,将“1”从第二个序列中删除
2. 找出两序列中剩余值中的最小值,作为目标序列的第二个值,并将这个最小值从原序列中“划掉”
由于“1”已被删除,此时比较“2”和“9”,选择“2”,将2从第一个序列中删除
3. 重复上述步骤直到两序列为空

由于每一步操作的运行时间都与输入规模无关(比较两个值,取最小值,删除最小值,将指针前移一位),因此每一步的运行时间都是Θ(1)\Theta(1)的。遍历两序列所有元素,需要n次,因此归并操作是Θ(n)\Theta(n)的。

归并排序时间复杂度分析

设总体时间复杂度为T(n)T(n),分别考虑以下3个步骤的时间复杂度:
1. 如果n = 1,排序完毕 —— 判断n是否为1,与输入规模无关,Θ(1)\Theta(1)(并不严格,为了简化问题,后续介绍)
2. 递归排序A[1,⌈n/2⌉]A[1, \lceil n/2 \rceil]和A[⌈n/2⌉+1,n]A[\lceil n/2 \rceil + 1, n] —— 2T(n/2)2T(n/2)(并不严格,后续介绍)
3. 合并两个排好序的序列 —— Θ(n)\Theta(n)

递归式

T(n)={Θ(1)ifn=1(通常会省略,对求解递归式没有影响)2T(n/2)+Θ(n)ifn>1

T(n)=\left\{ \begin{aligned} & \Theta(1) \quad if \quad n = 1 \quad (通常会省略,对求解递归式没有影响)\\& 2T(n/2) + \Theta(n) \quad if \quad n > 1 \\ \end{aligned} \right.
具体求解方法将在下节讲解,这里用图形化方法——递归树,进行直观的理解。

递归树

T(n)=2T(n/2)+cn常数c>0

T(n) = 2T(n/2) + cn \quad 常数c > 0

一直递推下去,会出现如下情形:

树高:n折半 log2nlog_2{n}次以后为1
叶子节点数:第i层有 2i−12^{i-1}个节点,第 log2n+1log_2{n}+1层有n个节点

计算总体时间复杂度:
第一层:cn
第二层:cn
…..
共有lgn个cn相加
最后一层:Θ(n)\Theta(n)
T(n)=(cn)lgn+Θ(n)=Θ(nlgn)T(n) = (cn)lgn+\Theta(n) = \Theta(nlgn)
从渐近的角度来开,在充分大的输入规模下(n>30),归并排序优于插入排序。

麻省理工大学公开课笔记:算法导论(二)——课程简介及算法分析相关推荐

  1. Python语言程序设计之urllib.request抓取页面,网易公开课之《麻省理工学院公开课:算法导论》

    Python语言用urllib.request模块抓取页面非常简单,再将抓取的页面内容用re模块解析,找出自己想要的东西.下面就就此方法来抓取网易公开课之<麻省理工学院公开课:算法导论>, ...

  2. 麻省理工公开课《算法导论》学习笔记:第一讲

    主题:简介课程,渐近概念的大局观,插入排序和归并排序,递归式函数时间分析(递归树方法) 教材:<算法导论> 收获:很感动地看到算法分析那个log(n)是为什么出现了,更深层还要听第二讲,若 ...

  3. 麻省理工大学公开课 离散数学

    网址: http://www.core.org.cn/OcwWeb/Electrical-Engineering-and-Computer-Science/6-042JSpring-2005/Lect ...

  4. 麻省理工公开课:线性代数》中文笔记来了

    MLNLP社区在Github上最新发布了一套MIT线性代数课程Linear Algebra的学习笔记,目前已获得1600star.项目简介如下所示,欢迎大家关注! 1.项目动机 <麻省理工公开课 ...

  5. 数据挖掘-理论与算法 公开课笔记

    数据挖掘-理论与算法 公开课笔记 制作:纪元 本提纲遵循CC-BY-NC-SA协议 (署名-非商业性-相同方式共享) 最近更新时间:2020年3月4日01:48:00 文章目录 10.2.1.1 Da ...

  6. Coursera公开课笔记: 斯坦福大学机器学习第十一课“机器学习系统设计(Machine learning system design)”

    Coursera公开课笔记: 斯坦福大学机器学习第十一课"机器学习系统设计(Machine learning system design)" 斯坦福大学机器学习斯坦福大学机器学习第 ...

  7. Coursera公开课笔记: 斯坦福大学机器学习第六课“逻辑回归(Logistic Regression)”

    Coursera公开课笔记: 斯坦福大学机器学习第六课"逻辑回归(Logistic Regression)" 斯坦福大学机器学习第六课"逻辑回归"学习笔记,本次 ...

  8. 详解爱奇艺ZoomAI视频增强技术的应用 | 公开课笔记

    嘉宾 | 蒋紫东 整理 | suiling 出品 | AI科技大本营(公众号ID:rgznai100) 看各种视频节目已经成为当前娱乐休闲的一种方式,技术的进步和网速的升级提升了我们的视觉愉悦感,但是 ...

  9. Coursera公开课笔记: 斯坦福大学机器学习第七课“正则化(Regularization)”

     Coursera公开课笔记: 斯坦福大学机器学习第七课"正则化(Regularization)" +13投票 斯坦福大学机器学习第七课"正则化"学习笔记, ...

  10. Coursera公开课笔记: 斯坦福大学机器学习第二课“单变量线性回归(Linear regression with one variable)”

    Coursera公开课笔记: 斯坦福大学机器学习第二课"单变量线性回归(Linear regression with one variable)" 发表于 2012年05月6号 由 ...

最新文章

  1. python caffe 在师兄的代码上修改成自己风格的代码
  2. 使用cocoapods时,import 找不到头文件。
  3. Centos sudo添加用户
  4. 超赞!12套你没见过的社交媒体 社交网站图标
  5. Html5 web本地存储
  6. HTML5媒体(音频/视频)
  7. python-3.8.0安装
  8. ssis 数据转换_SSIS数据透视和SSIS数据透视转换概述
  9. 通过Android上的意图启动Google地图路线
  10. ----流程控制-条件控制/循环控制\错误控制/程序终止控制
  11. Fedora9-ATI显卡Gnome环境下Amarok和EVA花屏现象理会及其处理责罚方法。
  12. ***HTML +CSS 总结与归纳
  13. Flash竖向大焦点图代码_网页代码站(www.webdm.cn)
  14. vuex的commit和dispatch
  15. 安卓手机(荣耀/vivo)下载以及安装Charles证书
  16. CSDN 写文章报错:标题含有非法字符,请修改的解决方法
  17. 弱口令总结(什么是弱口令)
  18. 我爱赚钱吧:建网站也是可以赚钱的③
  19. 可恶的RunDll广告怎么关闭
  20. ELK系列(四)、Logstash读取nginx日志写入ES中

热门文章

  1. BigDecimal,BigInteger 学习以及简单示例
  2. 小武与retinanet的斗争
  3. 儿童汽车拼图游戏 - 儿童游戏拼图2岁-5岁
  4. 数据库驱动程序是什么?
  5. Umap与 t-sne可视化CNN特征
  6. as3.0点击获取TLF文本的实例名
  7. springboot-2-整合myBatis及druid连接池
  8. 3. 'PipelinedRDD' object has no attribute '_jdf'
  9. 如何免费下载学术论文-谷粉学术
  10. ES数据的操作(二)