【趣学算法】算法的时空复杂性

本文深入探讨了算法的定义、特性以及评价标准,重点解析了时间复杂度和空间复杂度的概念。通过实例展示了如何计算时间复杂度,并对比了不同复杂度阶的增涨速度。同时,提到了在算法设计中应注重效率,力求降低时间与空间复杂度。
摘要由CSDN通过智能技术生成

14天阅读挑战赛
努力是为了不平庸~
算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法!欢迎记录下你的那些努力时刻(算法学习知识点/算法题解/遇到的算法bug/等等),在分享的同时加深对于算法的理解,同时吸收他人的奇思妙想,一起见证技术er的成长~

一、算法知识点

1.定义

算法是对特定问题求解步骤的一种描述,它不依赖于任何一种语言,既可以用自然语言、程序设计语言描述,也可以用流程图、框图来表示。通常情况下,为了更清楚地说明算法的本质,我们会去除计算机语言的语法规则和细节,采用“伪代码”来描述算法。

2.算法的特性

(1)有穷性:算法是由若干条指令组成的有穷序列,总是在执行若干次后结束,不可能永不停止。
(2)确定性:每条语句都有确定的含义,无歧义。
(3)可行性:算法在当前环境条件下可以通过有限次运算来实现。
(4)输入/输出:有零个或多个输入以及一个或多个输出。

3.“好”算法的标准
(1)正确性:正确性是指算法能够满足具体问题的需求,程序运行正常,无语法错误,能够通过典型的软件测试,达到预期。
(2)易读性:算法遵循标识符命名规则,简洁易懂,注释语句恰当适量,方便自己和他人阅读,便于后期调试和修改。
(3)健壮性:算法对非法数据及操作有较好的反应和处理。
(4)高效性:高效性是指算法运行效率高,即算法运行所消耗的时间短。
(5)低存储性:低存储性是指算法所需的存储空间小。对于像手机、平板电脑这样的嵌入式设备,算法如果占用空间过大,则无法运行。

二、时间复杂度:算法运行所需要的时间

//算法1
int sum = 0;  //运行1次
int total = 0;  //运行1次
for(int i = 1;i <= n;i++){  //运行n+1次
	sum = sum + i;  //运行n次
	for(j = 1;j <= n; j++)  //运行n×(n+1)次
		total = total + i*j;  //运行n×n次
}

算法1所有语句的运行次数相加起来:1+1+n+1+n+n×(n+1)+n×n。用函数T(n)表示为:
T ( n ) = 2 n 2 + 3 n + 3 T(n)=2n^2+3n+3 T(n)=2n2+3n+3
算法的运行时间主要取决于次数最高项,次数低项和常数可以忽略不计。

用极限可以表示为:
lim ⁡ n → ∞ T ( n ) f ( n ) = C ≠ 0 , C 为不等于 0 的常数 \lim_{n \to \infty} \frac{T(n)}{f(n)} =C≠0,C为不等于0的常数 nlimf(n)T(n)=C=0C为不等于0的常数
T ( n ) T(n) T(n) C f ( n ) Cf(n) Cf(n)的函数曲线如图1所示。从图1可以看出,当 n ≥ n 0 n≥n_0 nn0时, T ( n ) ≤ C f ( n ) T(n)≤Cf(n) T(n)Cf(n); 当n足够大时, T ( n ) T(n) T(n) f ( n ) f(n) f(n)近似相等。因此,我们用 O ( f ( n ) O(f(n) O(f(n)表示时间复杂度渐近上界,可以用这种表示法衡量算法的时间复杂度。
在这里插入图片描述

图1 时间复杂度渐近上界

渐近下界符号 Ω ( T ( n ) ≥ C f ( n ) ) Ω(T(n)≥Cf(n)) Ω(T(n)Cf(n)),如图2所示。从图2可以看出, 当 n ≥ n 0 n≥n_0 nn0时, T ( n ) ≥ C f ( n ) T(n)≥Cf(n) T(n)Cf(n); 当n足够大时, T ( n ) T(n) T(n) f ( n ) f(n) f(n)近似相等。因此,我们用 Ω ( f ( n ) ) Ω(f(n)) Ω(f(n))来表示时间复杂度渐近下界。

在这里插入图片描述

图2 时间复杂度渐近下界

渐近精确界符号 Θ ( C 1 f ( n ) ≤ T ( n ) ≤ C 2 f ( n ) ) \Theta (C_1f (n)≤T(n)≤C_2f(n)) Θ(C1f(n)T(n)C2f(n)),如图3所示。从图3可以看出,当 n ≥ n 0 n≥n_0 nn0时, C 1 f ( n ) ≤ T ( n ) ≤ C 2 f ( n ) C_1f(n)≤T(n)≤C_2f(n) C1f(n)T(n)C2f(n);当n足够大时, T ( n ) T(n) T(n) f ( n ) f(n) f(n)近似相等。这种两边逼近的方式更加精确近似,因此我们用 Θ ( f ( n ) ) \Theta (f(n)) Θ(f(n))来表示时间复杂度渐近精确界。
在这里插入图片描述

图3 渐近时间复杂度精确界

在实际应用中,通常使用时间复杂度渐近上界 O ( f ( n ) ) O(f(n)) O(f(n))来表示时间复杂度。

在算法分析中,渐近复杂度是对算法运行次数的粗略估计,大致反映问题规模增长趋势,而不必精确计算算法的运行时间。在计算渐近时间复杂度时,可以只考虑对算法运行时间贡献大的语句,而忽略那些运行次数少的语句。循环语句中处在循环内层的语句往往运行次数最多,它们是对运行时间贡献最大的语句。

注意:不是所有算法都能直接计算运行次数。

有些算法,如排序、查找、插入算法等,可以分为最好、最坏和平均情况分别求算法渐近复杂度。但考查个算法时通常考查最坏的情况,而不是考查最好的情况,最坏情况对衡量算法的好坏具有实际意义。

常见的算法时间复杂度有以下几类。
(1)常数阶。常数阶算法的运行次数是一个常数,通常用 O ( 1 ) O(1) O(1)表示。
(2)多项式阶。很多算法的时间复杂度是多项式,通常用 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( n 3 ) O(n^3) O(n3)等表示。
(3)指数阶。指数阶算法的运行效率极差,通常用 O ( 2 n ) O(2^n) O(2n) O ( n ! ) O(n!) O(n!) O ( n n ) O(n^n) O(nn)等表示。
(4)对数阶。对数阶算法的运行效率较高,通常用 O ( l o g n ) O(logn) O(logn) O ( n l o g n ) O(nlogn) O(nlogn)等表示。

指数阶增量随着 x x x的增加而急剧增加,而对数阶增长缓慢。它们之间的关系如下:
O ( 1 ) < O ( l o g n ) < O ( n ) < O ( n l o g n ) < O ( n 2 ) < O ( n 3 ) < 0 ( 2 n ) < O ( n ! ) < O ( n n ) O(1)< O(logn)< O(n)< O(nlogn) < O(n^2)< O(n^3)< 0(2^n) < O(n!)< O(n^n) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<0(2n)<O(n!)<O(nn)
在设计算法时,要注意算法复杂度增量的问题,尽量避免爆炸级增量。

三、空间复杂度:算法占用的空间大小

空间复杂度的本意是指算法在运行过程中占用了多少存储空间。算法占用的存储空间包括:
(1)输入/输出数据;
(2)算法本身;
(3)额外需要的辅助空间。

输入/输出数据占用的空间是必需的,算法本身占用的空间可以通过精简算法来缩减,但缩减的量是很小的,可以忽略不计。算法在运行时所使用的辅助变量占用的空间(即辅助空间)才是衡量算法空间复杂度的关键因素。

//算法2 交换x与y
void swap(int x, int y){
	int temp;
	temp = x;
	x = y;
	y = temp;
}

算法2使用了辅助空间temp,空间复杂度为O(1)。

在递归算法中,每一次递推都需要一个栈空间来保存调用记录, 因此在分析算法的空间复杂度时,需要计算递归栈的辅助空间。

//算法3 计算n的阶乘
int fac(int n){
	if(n == 0||n == 1)
		return 1;
	else
		return n*fac(n-1);
}

阶乘是典型的递归调用问题,递归包括递推和回归。递推是将原问题不断分解成子问题,直至满足结束条件,返回最近子问题的解;然后逆向逐一回归,最终到达递推开始的原问题,返回原问题的解。
以n=5为例,看一下计算机内部的处理过程,采用“栈”数据结构(特点:后进先出)

在这里插入图片描述

图4 5!的进栈过程

在这里插入图片描述

图5 5!的出栈过程

从图4和图5所示的进栈、出栈过程中可以很清晰地看到,子问题先被一步步地压进栈,直至直接可解得到返回值,再一步步地出栈,最终得到递归结果。在运算过程中,由于使用了n个栈空间作为辅助空间,因此阶乘递归算法的空间复杂度为O(n)。

算法3的时间复杂度也为O(n),因为n的阶乘仅比n-1的阶乘多了一次乘法运算 ( f a c ( n ) = n ∗ f a c ( n − 1 ) ) (fac(n)=n*fac(n-1)) (fac(n)=nfac(n1))。如果用T(n)表示fac(n)的时间复杂度,则可以表示为 T ( n ) = T ( n − 1 ) + 1 = T ( n − 2 ) + 1 + 1 = T ( 1 ) + . . . + 1 + 1 = n T(n)= T(n-1)+1= T(n-2)+1+1= T(1)+...+1+1=n T(n)=T(n1)+1=T(n2)+1+1=T(1)+...+1+1=n

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CS_木成河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值