文章目录
1. 空间复杂度
算法的空间复杂度是对执行过程中所需要的最大存储资源的开销的一种度量
衡量指标:
空间复杂度包括两个部分:
- 静态部分:与问题实例特性(用例个数的多少)无关的固定部分,比如代码空间,常数,定长变量。
- 动态部分:与实力特性相关的变化部分,包括:
- 和问题规模有关的输入输出
- 和问题规模相关的中间处理过程需要需要的空间、
- 递归栈空间
2. 时间复杂度
时间复杂度是对算法开始到结束所需要的执行时间的一种度量
衡量指标:程序步:
因为算法运行的时间和硬件性能相关,为了避免这种硬件带来的影响,时间复杂度的衡量单位需要屏蔽硬件差异,这就是程序步的意义所在。
程序步指的是算法中在语法和语义上有意义的指令序列,该序列的执行时间与算法的实例特性无关。具体而言,以下语句可以确定程序步:
- 注释:0步
- 函数:0步,因为其代价已经算在函数调用中
- 函数调用:执行该函数的程序步数
- 表达式:若不包含函数调用,则为1;若包含,则累加
- 赋值语句:与表达式所需要的程序步数相同
- 循环控制语句部分:
- while(<表达式>):等于表达式执行的次数
- for:(<初始化>;<表达式1>;<表达式2>):第一次:<初始化>+<表达式1>;之后:<表达式1>+<表达式2>
- switch(<表达式>) case<条件>:<语句>:每次执行,消耗:<表达式>+成功的case的<条件>+<语句> + 其前面所有失败的case的<条件>之和
3. O表示法
O表示法做的是对原本的程序步做进一步的抽象,核心想法就是,只留下最高次的数量级。做了两次抽象:
1. 去掉了不是其主要作用的项;
2. 对于起主要作用的项,去除其前面的常数,改为1
O表示法可以用来表示时间复杂度,也可以用来表示空间复杂度
定义:
f(n)=O(g(n)) 当且仅当存在正值常数 c和n0 ,使得对于所有的 n≥n0 ,有 f(n)≤c∗g(n) (含义是: c∗g(n) 是 f(n) 的上界)。为了表示更精确的信息, g(n) 应该取满足条件的最小的函数。
计算方法
虽然我们可以通过计算准确的程序步来计算O(),但是这样的做法不是很有效率,我们可以通过确定每一组语句的渐进复杂性,然后汇总推导得到
例子:计算BinarySearch的最坏时间复杂性:
T(0)=a
T(n)=b+T(n/2)=b∗2+T(n/22)=...=b∗log2n+T(0)=O(logn)
空间复杂度的计算:
一个算法的空间复杂度只考虑在运行过程中为局部变量分配的存储空间的大小,它包括为参数表中形参变量分配的存储空间和为在函数体中定义的局部变量分配的存储空间两个部分。
- 递归算法,其空间复杂度为递归所使用的堆栈空间的大小,它等于一次调用所分配的临时存储空间的大小乘以被调用的次数(即为递归调用的次数加1,这个1表示开始进行的一次非递归调用)。
- 非递归算法:直接看在算法执行过程中与规模特性相关的临时存储空间的大小之和。若当一个算法,不随被处理数据量n的大小而改变时,可表示为O(1);
4. 代价分摊
代价分摊的思路是:孤立地看待每一个调用程序的最坏时间复杂度,来累加程序最终的时间复杂度,会导致一个比较糟糕的结果。所以提出代价均摊的方案,核心的思想是:通过对每个状态S,赋予实数 Φ(S) ,称为S的势能,用来表示S进行高代价操作的可能性。具体怎么做,此坑待填。