渐进分析 Note

  • 1. Introdiction
  • 2. Big-Theta Notation - Θ\ThetaΘ
    • 2.1 Example-Duplicate Detection
      • 2.1.1 小实验(运行时间随规模增加的变化)
    • 2.2一般描述算法复杂性的方法
      • 2.2.1使用python计时器进行精确评估
      • 2.2.2 计算代码中每一步的调用次数
        • 2.2.2.1 对“调用次数”指标进行简化
    • 2.3 Big theta-Θ\ThetaΘ

1. Introdiction

渐进分析 (Asymptotic Analysis)主要用于评估代码的性能
Old saying:
An engineer will do for a dim what any fool will do for a dollar.

垃圾的代码: 使用不合适的数据结构、复杂、缓慢、占用大量内存
好的代码:合适的数据结构、简洁、高效、使用合理的内存开销

2. Big-Theta Notation - Θ\ThetaΘ

2.1 Example-Duplicate Detection

考虑分析在如下的列表中,查找出重复元素的两种方法的算法复杂度:

-3 -1 2 4 4 8 12

implimentation of comparing algorithm
Object: 查找array中是否存在重复的元素
Determine if their is any duplicates in the array。
一个基本的想法是考虑所有可能的情况
A silly method

def sillySearch(x):OperationCount = 0print('I compare every possible pair!')lengthOfX = len(x)for _ in range(lengthOfX):currentA = x[_]for i in range(_+1,lengthOfX):OperationCount +=1print("Comparing ",str(x[_])+"=="+str(x[i]),"Operation Count: ",str(OperationCount))if x[_]==x[i]:print(str(x[_])+"="+str(x[i]))return True

程序输出:

I compare every possible pair!
Comparing  -3==-1 Operation Count:  1
Comparing  -3==2 Operation Count:  2
Comparing  -3==4 Operation Count:  3
Comparing  -3==4 Operation Count:  4
Comparing  -3==8 Operation Count:  5
Comparing  -3==12 Operation Count:  6
Comparing  -1==2 Operation Count:  7
Comparing  -1==4 Operation Count:  8
Comparing  -1==4 Operation Count:  9
Comparing  -1==8 Operation Count:  10
Comparing  -1==12 Operation Count:  11
Comparing  2==4 Operation Count:  12
Comparing  2==4 Operation Count:  13
Comparing  2==8 Operation Count:  14
Comparing  2==12 Operation Count:  15
Comparing  4==4 Operation Count:  16
4=4
0:00:00.000192
[Finished in 1.9s]

一个更好的方法是只考虑相邻的情况

# a little bit cleverer method
# only consider the neighboring duplication
def betterSearch(x):OperationCount = 0print('I compare neighboring pairs!')lengthOfX = len(x)for _ in range(lengthOfX):currentA = x[_]OperationCount +=1print("Comparing ",str(x[_])+"=="+str(x[_+1]),"Operation Count: ",str(OperationCount))if x[_]==x[_+1]:print(str(x[_])+"="+str(x[_+1]))return True

程序输出:

I compare neighboring pairs!
Comparing  -3==-1 Operation Count:  1
Comparing  -1==2 Operation Count:  2
Comparing  2==4 Operation Count:  3
Comparing  4==4 Operation Count:  4
4=4
0:00:00.000059
[Finished in 1.7s]

记nnn为比较(======)的次数。
比较silly的baseline方法用了192个单位时间。n=16n=16n=16
改进的方法用了59个单位时间.n=4n=4n=4
where nnn is the count of the operating steps

2.1.1 小实验(运行时间随规模增加的变化)

在最坏的情况下(把重复项放到数组x的末尾),两种查重算法的运行时间(ms)与数组xxx的长度的关系。可见随着数组长度增加,silly方法的运行情况指数级恶化。

但是,在最好的情况下(数组中所有元素相同),二者的表现相差不大:
此时用x = [0]*N对数组x 进行初始化

测试并绘图使用的源代码如下:

# A silly method
def sillySearch(x):OperationCount = 0# print('I compare every possible pair!')lengthOfX = len(x)for _ in range(lengthOfX):currentA = x[_]for i in range(_+1,lengthOfX):OperationCount +=1# print("Comparing if x[_]==x[i]:return True# a little bit cleverer method
# only consider the neighboring duplication
def betterSearch(x):OperationCount = 0# print('I compare neighboring pairs!')lengthOfX = len(x)for _ in range(lengthOfX-1):currentA = x[_]OperationCount +=1if x[_]==x[_+1]:# print(str(x[_])+"="+str(x[_+1]))return Trueimport datetime
from matplotlib import pyplot as plt
# x = [-3,-1,2,4,4,8,12]sillyRecorder = []
betterRecorder = []
#test silly
for N in range(1,1000,100):x = list(range(0,N-1))x.append(N-2)start = datetime.datetime.now()sillySearch(x)# do somethingend = datetime.datetime.now()sillyRecorder.append((end-start).microseconds)
for N in range(1,1000,100):x = list(range(0,N-1))x.append(N-2)start = datetime.datetime.now()betterSearch(x)end = datetime.datetime.now()betterRecorder.append((end-start).microseconds)plt.plot(sillyRecorder)
plt.plot(betterRecorder)
plt.legend(['silly','better'])
plt.show()
plt.xlabel('length of array')
plt.xlabel('Running Time (/ms)')
print(sillyRecorder)

2.2一般描述算法复杂性的方法

为了描绘一个算法的复杂性,需要建立一种同时具有简单(simple)和数学严谨性(mathematically rigious)的描述方法,使得上述两种算法的复杂度一目了然。首先来看一下常见的描述算法性能的方法,然后逐渐过渡到Big-Theta Notation - Θ\ThetaΘ。

2.2.1使用python计时器进行精确评估

1:对python文件的运行时间进行计时

在终端中输入:
>> time python 文件名

2: 对指定代码块的运行时间进行计时

import datetime
start = datetime.datetime.now()
代码块
end = datetime.datetime.now()
print (end-start)

2.2.2 计算代码中每一步的调用次数

考虑到算法规模为NNN的情况(即待查找的list长度为NNN),
对于比较“笨”的这种算法:

def sillySearch(x):lengthOfX = len(x)for _ in range(lengthOfX):currentA = x[_]for i in range(_+1,lengthOfX):OperationCount +=1if x[_]==x[i]:print(str(x[_])+"="+str(x[i]))return True

各个功能块的执行次数、最好的情况到最差的情况如下:

Operation Count
range calls 2 to N+1N+1N+1
len calls 2 to N+1N+1N+1
_ assignments 1 to N−1N-1N−1
j assignments 1 to N2−N2\frac{N^2-N}{2}2N2−N​
equals(==) 1 to N2−N2\frac{N^2-N}{2}2N2−N​
array access) 2 to N2−NN^2-NN2−N

对于比较聪明的算法:

# a little bit cleverer method
# only consider the neighboring duplication
def betterSearch(x):OperationCount = 0lengthOfX = len(x)for _ in range(lengthOfX):currentA = x[_]OperationCount +=1if x[_]==x[_+1]:return True

各个功能块的执行次数、最好的情况到最差的情况如下:

Operation Count
range calls 1
len calls 1
_ assignments 1 to N−1N-1N−1
equals(==) 1 to N−1N-1N−1
array access) 2 to 2N−22N-22N−2
2.2.2.1 对“调用次数”指标进行简化

我们可以依据以下规则对上述的评估方式进行适当简化:

  1. 只考虑最差的情况(Only consider the worst case)
  2. 选择具有代表性的操作(Representative Operation)
  3. 忽略低次项(Ignore lower order terms)
  4. 忽略乘法计算的常系数 (Ignore multiplicative constant)
    假设说有这么一个算法的操作计数表:
Operation Count
Op_1 1
Op_2 1 to NNN
Op_3 1 to N2−N2\frac{N^2-N}{2}2N2−N​
Op_4 0 to N2+3N+22\frac{N^2+3N+2}{2}2N2+3N+2​

这个表可以被进一步简化为:

Operation Count
Op_3 N2N^2N2

于是现在就有以一种基于数学假设的更严谨的方式,使用N2N^2N2来刻画这个算法的复杂度。

实际上一个算法的复杂度取决于最最糟糕的情况下,操作复杂度增长的数量级。

2.3 Big theta-Θ\ThetaΘ

-Example: Q(N)=3N3+N2Q(N)=3N^3+N^2Q(N)=3N3+N2
-Order of growth: N3N^3N3

function Order of growth
N3+3N4N^3+3N^4N3+3N4 N4N^4N4
1N+N3\frac{1}{N}+N^3N1​+N3 N3N^3N3
1N+5\frac{1}{N}+5N1​+5 1
NeN+NNe^N+NNeN+N NeNNe^NNeN
40∗sin(N)+4N240*sin(N)+4N^240∗sin(N)+4N2 N2N^2N2

Big-Theta的定义:
假设我们有一个函数R(N)R(N)R(N),有一个增长的order f(N)f(N)f(N)(order of growth)。
在“Big-Theta” 的标记方式里,我们把这个关系写为:
R(N)∈Θ(f(N))R(N)\in \Theta(f(N))R(N)∈Θ(f(N))
例如:

  • N3+3N4∈Θ(N4)N^3+3N^4\in\Theta(N^4)N3+3N4∈Θ(N4)
  • 1N+N3∈Θ(N3)\frac{1}{N}+N^3\in \Theta(N^3)N1​+N3∈Θ(N3)
  • 1N+5∈Θ(1)\frac{1}{N}+5\in\Theta(1)N1​+5∈Θ(1)
  • NeN+N∈Θ(NeN)Ne^N+N\in\Theta(Ne^N)NeN+N∈Θ(NeN)
  • 40∗sin(N)+4N2∈Θ(N2)40*sin(N)+4N^2\in\Theta(N^2)40∗sin(N)+4N2∈Θ(N2)
    注意,有的情况下,有人会选择将上述的∈\in∈换成===。

更具体而言,当我们说R(N)∈Θ(f(N))R(N)\in \Theta(f(N))R(N)∈Θ(f(N))的时候,等价于存在两个为正的常数
k1k_1k1​和k2k_2k2​, 于是有:
k1⋅f(N)≤R(N)≤k2⋅f(N)k_1\cdot f(N)\leq R(N)\leq k_2\cdot f(N)k1​⋅f(N)≤R(N)≤k2​⋅f(N)
对于所有的NNN当N0≤NN_0 \leq NN0​≤N时成立

算法复杂度-渐进分析 (Asymptotic Analysis)相关推荐

  1. 算法复杂度-渐进分析

    算法复杂度-渐进分析 渐进表达式的定义 渐进上界 大OOO O(g(n))={f(n):∃c>0,n0>0.s.t.∀n≥n0,0≤f(n)≤cg(n)}O(g(n)) = \{f(n): ...

  2. 数据结构 | 十大排序超硬核八万字详解【附动图演示、算法复杂度性能分析】

    写在前面 2023年的第一篇博客,在这里先祝大家兔年快乐

  3. 【数据结构】算法的渐进分析-渐进时间复杂度

     算法的渐进分析(asymptotic algorithm analysis)简称算法分析.算法分析直接与它所求解的问题的规模 n 有关,因此,通常将问题规模作为分析的参数,求算法的时间和空间开销与问 ...

  4. 二分检索用途及复杂性_二分查找和三分查找哪个快?算法复杂度与常数无关?复杂度分析的常见误区...

    还记得两三年前,我初看一本算法书,看到二分查找算法的复杂度时,我发现了了不得的东西:二分查找每次查询范围减少一半,需要查询的次数是 ,它的复杂度是 . 我把它改成三分查找,每次查询两个数字与我的目标数 ...

  5. 算法复杂度及渐进符号

    算法复杂度及渐进符号 一.算法复杂度 每一个程序在运行时,都需要占用一定的计算机资源,比如内存,磁盘,这些称之为空间. 计算过程中需要判断,循环执行某些逻辑,周而反复,这些是时间. 那么我们可以通过算 ...

  6. 算法时间复杂度的渐进表示法 + 分析窍门

    如果算法里面只有加减法,则算法时间算加减法的次数. 如果算法里面包含加法和乘法,则算法时间一般只算乘法次数,因为计算机计算加减法很快,可忽略. 问题:什么是好的算法? 一个程序的运行时间,依赖与算法的 ...

  7. Asymptotic Analysis——渐近分析

    上图主要介绍的是渐进分析的动机是什么. 高级推理算法的"灵魂"(翻译水平有限,不知道合适不合适,若有好的翻译请告诉我,或者你直接看英文原版吧) 不关注架构/语言/编译器的相关细节( ...

  8. 图的链接分析 (link analysis): PageRank 算法

    目录 PageRank 的定义 前置知识 基本想法 PageRank 的基本定义 PageRank 的一般定义 PageRank 的计算 代数算法 迭代算法 幂法 (power method) Why ...

  9. 【天赢金创】算法复杂度分析

    原文:http://www.cnblogs.com/gaochundong/p/complexity_of_algorithms.html 为什么要进行算法分析? 预测算法所需的资源 计算时间(CPU ...

  10. 算法复杂度分析(下)

    前一篇文章算法复杂度分析(上)讲述了复杂度的大 O 表示法和几个分析原则,这篇文章我们来讲讲另外几种复杂度,最好情况时间复杂度(best case time complexity).最坏情况时间复杂度 ...

最新文章

  1. 如何对DevOps数据库进行源代码控制
  2. eclipse配置maven + 创建maven项目
  3. ubuntu 64 12.04 oracle,ubuntu server 12.04 x86_64 下安装oracle xe 11 x86_64
  4. linux系统lsmod命令,linux lsmod命令 及相关信息
  5. [转载]使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案
  6. 分布式文件系统-HDFS(   HDFS全称是Hadoop Distributed System)
  7. Illustrator 教程,如何在 Illustrator 中创建标签?
  8. BZOJ1086 [SCOI2005]王室联邦(树分块)
  9. modbus tcp主站和从站_图文讲解PLC通讯MODBUS协议的应用及编程
  10. 追求代码质量: 使用 TestNG-Abbot 实现自动化 GUI 测试
  11. C++实现金山打字通助手
  12. unity 摄像头跟着鼠标移动_lwj_unity_模拟第一人称摄像机前后左右移动、摄像机随鼠标移动旋转、鼠标点击添加物体...
  13. 【最大公约数】欧几里得算法
  14. V2X方案之OBU介绍
  15. md4 java_求MD4 java实现的代码
  16. aspen压缩因子_ASPEN PLUS的物性数据库及其应用.pdf
  17. 新型病毒DoubleAgent 先入侵杀毒软件
  18. MySQL||主键(primary key)及主键约束
  19. 你处在人生的哪个阶段
  20. HR在线招人,快甩简历啦

热门文章

  1. stm32 带通滤波器_带通滤波器详解_带通滤波器工作原理_带通滤波器原理图
  2. access数据库应用系统客观题_Access数据库程序设计模拟题
  3. 【软件体系结构】软件体系结构风格
  4. 谷歌浏览器翻译栏_将Google翻译栏添加到您喜欢的浏览器
  5. 消息钩子函数入门篇(1)--基础知识
  6. 设计文档应该怎么写?
  7. 网赚项目之站群第一课如何利用站群快速赚钱
  8. 在Ubuntu中下载github上的文件
  9. \t\t产后饮食标准 饮食原则 最适合新妈妈吃的菜 饮食秘诀 禁忌
  10. 甘特图首选解决方案-世界级甘特图控件(XGANTT) - XGantt甘特图中文官方网站