算法是对问题解决步骤的描述,通过有限序列的指令来实现。
一. 五大特征:
-
有穷性:有限步之后结束
-
确定性:不存在二义性,即没有歧义
-
可行性:比如受限于计算机的计算能力,有些算法理论上可行,但实际上无法完成
-
输入:能被计算机处理的各种类型数据,比如数字,音频,图像等
-
输出:一至多个程序输出结果
总结:输入–有限,可行,正确的算法—>输出
二. 算法的复杂度
时间复杂度:
- 用来衡量算法随着问题规模的增大,算法执行时间增长的快慢
- 是问题规模的函数,T(n)是时间规模函数,时间复杂度主要分析T(n)的数量级(分析T(n)的数量级就是分析关于n的项,是最大处于哪个级别,0次项,一次项还是平方项)
- T(n)=O(f(n)) , f(n)是算法中基本运算的频度,一般我们考虑最坏情况下的时间复杂度(基本运算是出现频数最多的运算)
空间复杂度:
-
它用来衡量算法随着问题规模的增大,算法所需空间增长的快慢
-
是问题规模的函数:S(n) =O(g(n)) 算法所需空间的增长率和g(n)的增长率相同
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kjdrSUYj-1590850654576)(C:\Users\May天\AppData\Roaming\Typora\typora-user-images\image-20200530020740800.png)]
从上图可以看出,随着问题规模的增大,所需时间的增长率(斜率)差别很大,而且,这个差距随着问题规模的增大而显著地增大。
我们关心的就是算法的这个增长规模速度
常用的时间复杂度大小关系:
O(1) <O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2^n)
从左至右,时间性能依次降低。
PS: log2n更多写成logn
三. 计算算法的时间复杂度
给出一段程序,然后要求计算时间复杂度
- 示例一
int sum = 0;
for(int i=0; i<n; i++){
sum = sum +i;
}
int sum = 0;
执行一次。 int i = 0
执行一次。i<n
执行n+2次,i++
执行 n+1次
sum = sum+i
执行n+1次.
时间分析:该算法执行了3n+6个语句。假设每个语句执行的时间一致,均为常数 t,则总时间T=(3n+6)t
随着问题规模的增大,则总时间的增长率和n 的增长率一致,所以复杂度为O(n)
结论:
- 复杂度是关于增长率的,所以可以直接忽略常数
- 一般可以直接关注循环段基本操作语句(示例中sum = sum+i)的执行次数
- 时间复杂度是O(n)
-
示例二 时间复杂度计算(单个循环体)
直接关注循环体的执行次数,设为k
int sum=0; for(int i =1; i<=n; i=2*i){ sum = sum+i; }
i取值:1 2 4 8
满足条件:2^k<n
k>log2n时,跳出循环,所以循环体执行次数[log2n]
故时间复杂度为O(logn)
-
示例三 时间复杂度计算(多个循环体)
两个运算规则:乘法规则,加法规则
加法规则:
for(i=1; i<=n; i++){ x++; } for(i=1; i<=n; i++){ for(j=1; j<=n; j++){ x++; } }
两个循环体是独立的,采用加法规则:T(n) = T1(n)+T2(n)=max(T1(n), T2(n))=O(n^2)
乘法规则:
for(int i=1; i<=n; i++){
for(int j=1; i<=n; j=2*j){
sum=sum+j;
}
}
T(n)=T1(n)*T2(n)=O(n) * O(logn) = O(nlogn)
四. 算法的空间复杂度的计算
空间复杂度S(n)指算法运行过程中所使用的辅助空间的大小。记为:
S(n)=O(f(n))
- 辅助空间:除了存储算法本身的指令,常数,变量和输入数据外,还需要存储对数据操作的存储单元
- 算法原地工作是指算法所需的辅助空间是常量,即O(1)
空间复杂度的计算
空间复杂度S(n)指算法运行过程中所使用的辅助空间的大小。记为:
S(n)=O(f(n))
- 辅助空间:除了存储算法本身的指令,常数,变量和输入数据外,还需要存储对数据操作的存储单元
- 算法原地工作是指算法所需的辅助空间是常量,即O(1)