《算法导论》第三章 函数的增长 个人心得——记号与常用函数
由第二章中我们得知,算法的时间复杂度只与算法的高阶项有关。当输入规模n足够大时,高阶项的花费远超过低阶项。因此在计算算法的运行时间时,尽管可以求出精确的运行时间,但是并不值得我们这么做。
在n很大的情况下,我们更感兴趣的是算法的渐进效率,即,当输入规模无限增加时,在极限中,算法的运行时间如何随着输入规模的变大而变大。
这一章首先介绍了几个“渐进记号”,其中,我们见过Θ记号。然后,我们简单介绍几个函数以及性质。
一、渐进记号
我们用渐进记号来刻画算法的运行时间,以便于方便的描述最坏运行时间函数T(n)。
本章主要介绍Θ、O、Ω记号,以及相对应的θ、o、ω记号(注意大小写)。
上图给出了f(n)与g(n)的关系。标出的n0是最小的可能值。任何大于n0的值都有效。在图一中,表示Θ记号,即将f(n)限制在c1g(n)与c2g(n)之间,给出了f(n)的上下界。图二中表示O记号,给出函数f(n)的上界。图三中表示Ω记号,给出f(n)的下界
Θ记号
由第二章,我们知道插入排序的最坏时间是T(n)=Θ(n²)。我们给出这个记号的定义:对于一个给定的函数g(n),Θ(g(n))表示以下函数的集合:
θ(g(n))={f(n):存在常量c1、c2 和 n0,使得对所有n≥n0,有0≤c1g(n)≤f(n)≤c2g(n)}(在集合中,冒号的含义是“使得”)
通俗的说,就是Θ(g(n))表示满足0≤c1g(n)≤f(n)≤c2g(n)的f(n)函数的集合。因为Θ(g(n))是一个集合,可以记作“f(n)∈Θ(g(n))”,以指出f(n)是Θ(g(n))集合中的一员。但是我们通常记作“f(n)=Θ(g(n))”。
由Θ(g(n))的定义可知,每个成员f(n)∈Θ(g(n))均渐进非负。因此,g(n)本身也是渐进非负,否则集合Θ(g(n))为空。我们假设在Θ记号内的每个函数都是渐进非负的。这个假设对其他记号也成立。
O记号
Θ记号给出了函数的上界和下界,而当只有一个渐进上界时使用O记号。对于一个给定的函数g(n),O(g(n))表示以下函数的集合:
O(g(n))={f(n):存在常量c和 n0,使得对所有n≥n0,有0≤f(n)≤cg(n)}
O记号给出了函数的一个在常量因子的上界,在衡量算法的时间复杂度时,我们通常比较算法的最坏时间,所以多数情况下时间复杂度用该记号表示,被称为大O表示法。
我们记f(n)=O(g(n))以指出f(n)是集合O(g(n))的成员。但是注意,f(n)=Θ(g(n))包含着f(n)=O(g(n))。
Ω记号
与O记号相反,当只有一个渐进下届时使用Ω记号,相应的定义为:
Ω(g(n))={f(n):存在常量c和 n0,使得对所有n≥n0,有0≤cg(n)≤f(n)}
Ω记号通常表示最好的情况,例如,插入排序的最好运行时间为Ω(n)。
等式和不等式中的渐进记号
当渐进记号独立于等式或不等式的右边时,我们已经定义等号意味着指出了集合的成员关系。如对n= O(n²),我们是指n∈O(n²)。然而,当渐进记号出现在某个公式中,我们通常解释为我们所不关注名称的匿名函数。
例如,在公式2n²+3n+1=2n²+Θ(n)指的是2n²+3n+1=2n²+f(n)。f(n)是集合Θ(n)中的某个函数。安好这种方式可以帮助消除一个等式中无关紧要的细节与混乱。使得等式更清晰,方便我们抓住重点。例如,在第二章中,归并排序的最坏运行时间我们表示为递归式T(n)=2T(n/2)+Θ(n)。如果只对T(n)的渐进行为感兴趣,那么没有必要把所有低阶项都准确说出来,用包含在Θ(n)中的匿名函数代指他们。
在某些例子中,渐进记号也出现在等式的左边,如:2n²+Θ(n)=Θ(n²),这该如何解释?
我们将其解释为:无论怎样选择等号左边的匿名函数,总有一种办法来选择等号右边的匿名函数使得等式成立。也就是说,对任意函数f(n)∈Θ(n),存在某个函数g(n)∈Θ(n²),使得对所有的n,有2n²+f(n)=g(n)。可以看出,等式左边提供了更多的细节,等式右边更粗糙。当我们把很多个这样的关系链在一起,你就会看的更明白:
2n²+3n+1=2n²+Θ(n)=Θ(n²)
看到了吧,最左边的式子提供了很多具体细节,他将二次项、一次项、常数项都清楚的指出来。而当到第二个式子时,3n+1被泛化成了Θ(n),而在最右边,所有的项都被泛化成最高阶项的集合Θ(n²)。
o记号
由大O记号提供的渐进上界可能是渐进紧确的也可能不是渐进紧确的。例如,界2n²=O(n²)时渐进紧确的,而界2n=O(n²)就不是。当出现这种情况时,我们用o记号来表示一个非渐进紧确的上界。o(g(n))定义为:
o(g(n))={f(n):对任意正常量c>0,存在常量n0>0,使得对所有n>=n0,有0<=f(n)<=cg(n)}
例如2n=o(n²),但是2n²≠o(n²)
从定义上来看,O与o类似,区别是在f(n)=O(g(n))中,界0<=f(n)<=cg(n)对某个常量c>0成立,而在f(n)=o(g(n))中,界0<=f(n)<cg(n)对所有c>0都成立。
在o记号中,当n趋于无穷时,函数f(n)相较与g(n)变得微不足道了,即
limn→∞f(n)/g(n)=0
ω记号
ω与Ω记号的关系和o与O记号关系类似。我们使用ω来表示一个渐进非紧确的下界。定义为:
ω(g(n))={f(n):对任意正常量c>0,存在常量n0>0,使得对所有n>=n0,有0<=cg(n)<f(n)}
他的另一种定义方式是:
f(n)∈ω(g(n))当且仅当g(n)∈o(f(n))
例如:n²/2=ω(n),但是n²/2≠ω(n²)。关系f(n)=ω(g(n))蕴含着
limn→∞f(n)/g(n)=∞
也就是说,如果这个极限存在,当n趋于∞时,f(n)相对于g(n)来说变得任意大了。
各种函数性质
实数的许多关系性质也适用于渐进比较。下面假定f(n)和g(n)渐进为正。
传递性
f(n)=Θ(g(n))且g(n)=Θ(h(n)),则蕴含着f(n)=Θ(h(n))
f(n)=O(g(n))且g(n)=O(h(n)),则蕴含着f(n)=O(h(n))
f(n)=Ω(g(n))且g(n)=Ω(h(n)),则蕴含着f(n)=Ω(h(n))
f(n)=o(g(n))且g(n)=o(h(n)),则蕴含着f(n)=o(h(n))
f(n)=ω(g(n))且g(n)=ω(h(n)),则蕴含着f(n)=ω(h(n))
自反性
f(n)=Θ(f(n))
f(n)=O(f(n))
f(n)=Ω(f(n))
对称性
f(n)=Θ(g(n))当且仅当g(n)=Θ(f(n))
转置对称性
f(n)=O(g(n))当且仅当g(n)=Ω(f(n))
f(n)=o(g(n))当且仅当g(n)=ω(f(n))
二、标准记号与常用函数
本书里用到的大多数数学函数与记号在学习生涯中基本都学过,这里不再赘述,只简单介绍一下斐波那契数列。
斐波那契数列
按照下面的递归式定义斐波那契数列:
F0=0
F1=1
F2=F0+F1=1
F3=F2+F1=2
…
Fn=Fn-1 + Fn-2,n大于等于2
即从第三项开始,每一项都是前两项的和。
斐波那契数列的通项公式为:
扩展:通项公式推导(来源:百度百科——斐波那契数列)
利用特征方程(线性代数解法)
线性递推数列的特征方程为:
x²=x+1
解得
则
解得
(完)
《算法导论》第三章 函数的增长 个人心得——记号与常用函数相关推荐
- 算法导论第三版第十一章11.1-4
算法导论第三版第十一章11.1-4 我们希望在一个非常大的数组上,通过利用直接寻址的方式来实现一个字典.开始时,该数组中可能包含一些无用信息,但要堆整个数组进行初始化时不太实际的,因为该数组的规模太大 ...
- 带权中位数-算法导论第三版第九章思考题9-2
带权中位数-算法导论第三版第九章思考题9-2 b 时间复杂度O(nlgn) float find_median_with_weights_b(float *array,int length) {qui ...
- 算法导论第三版第二章思考题答案
算法导论第三版第二章思考题答案 第二章思考题 算法导论第三版第二章思考题答案 2.1 2.2 2.3 2.4 汇总传送门 2.1 #include<iostream> using name ...
- 找出第i个小元素(算法导论第三版9.2-4题)
找出第i个小元素(算法导论第三版9.2-4题) 期望时间复杂度:Θ(n) 最坏情况的时间复杂度Θ(n^2) int randomized_select_based_loop(int *array,in ...
- 软件工程导论第三章复习总结附思维导图
软件工程导论第三章复习总结附思维导图 概述 准确回答"系统必须做什么" 必须理解并描述问题的信息域,根据这条准则应该建立数据模型 必须定义软件应该完成的功能,这条准则要求建立功能模 ...
- 算法导论第三版3.1答案
算法导论第三版3.1答案 这一章数学公式实在太多了..打不过来,为了节约时间就用纸笔写了. 2.2 算法导论第三版3.1答案 汇总传送门 汇总传送门 链接: [算法导论习题答案汇总]
- 给出TREE_INSERT过程的非递归版本(算法导论第三版12.3-1)
给出TREE_INSERT过程的非递归版本(算法导论第三版12.3-1) template<typename T> void insert_recursive(BinaryTree< ...
- 写出TREE-PREDECESSOR的伪代码(算法导论第三版12.2-3)
写出TREE-PREDECESSOR的伪代码(算法导论第三版12.2-3) TREE-PREDECESSOR(x)if x.left != NILreturn TREE-MAXIMUM(x.left) ...
- 写出TREE-MINIMUM 和TREE-MAXIMUM的递归版本(算法导论第三版12.2-2)
写出TREE-MINIMUM 和TREE-MAXIMUM的递归版本(算法导论第三版12.2-2) template<typename T> BinaryTreeNode<T>* ...
最新文章
- VINS-mono详细解读与实现
- 「图文直播」CSDN 二十年,AI 赋能全新出发
- 与 Linux 一起学习:学习打字
- Python字典理解
- databricks使用
- mysql dba系统学习(2)了解mysql的源码目录及源文件
- Python3的unittest用例按编写顺序执行
- socket编程实现文件传输功能
- Linux工作笔记033---Linux(CentOS7)安装zip、unzip命令
- mysql对sql的支持并不是太好_MySQL数据库优化总结
- javascript 编程指南
- 构成vspher虚拟化平台所需构建概念
- iwconfig命令
- Ubuntu 16.04 安装 搜狗输入法
- gtk3基础知识的学习(C语言)
- 错误Could not locate executable null\bin\winutils.exe in the Hadoop binaries的解决方案
- codeforces 884B Japanese Crosswords Strike Back
- AssertionError: Attempted unscale_ but _scale is None
- Hutool - 对于网络的一些方法和增强
- vue项目落地(qiankun.js)微前端服务
热门文章
- 非科班的我拿到了网易自然语言处理实习offer
- MySQL数据类型int、bigint、smallint 和 tinyint的区别
- 二本计算机考研简单吗,二本考生考研一本院校难不难?不要听那些奇怪论调,而要看这些!...
- RPGMaker MV 插件基础02:插件的参数定义
- C和C++的区别大赏
- Docker 完整基础 (续) (二)
- 15.OpenWrt-U盘和TF卡存储
- java字符集编码_Java字符集编码
- 安忆往昔的唯美伤感空间日志发布:那杯白开水,很伤很美
- 日常英语-从起床到出门