当前位置: 首页 > news >正文

怎样计算一个算法的复杂度?

分析一个算法主要看这个算法的执行需要多少机器资源。在各种机器资源中,时间和空间是两个最主要的方面。因此,在进行算法分析时,人们最关心的就是运行算法所要花费的时间和算法中使用的各种数据所占用的空间资源。算法所花费的时间通常称为时间复杂度,使用的空间资源称为空间复杂度。接下来学习如何计算一个算法的时间复杂度和空间复杂度。

1.时间复杂度

在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,然后分析T(n)随n的变化。

1653989744854_41.png

这样用大写的O来标记算法的时间复杂度,称之为大O(Order的简写)标记法。一般随着n的增长,T(n)也会随之增长,其中T(n
)增长最慢者就是时间性能最优的算法。

在计算时间复杂度的时候,根据T(n)与n的最高阶数关系,我们给这些算法的复杂度进行了归类,如表1所示。
1653991095252_42.png

当然还会有一些其他阶数关系,这里只是列出了几种较常见的关系。算法的执行次数可能会与规模n呈现出这些关系,那么这些关系又是如何推导出来的呢?下面给出大O阶的推导方法:

(1)用常数1取代运行中的所有加法常数。

(2)在修改后的运行次数函数中,只保留最高阶项。

(3)如果最高阶项存在,且不是1,则除去其常系数,得到的结果就是大O阶。

接下来通过分析几段程序的执行过程来推导出其时间复杂度,程序段1代码如下所示:

int a=100;              //执行一次int b=200;              //执行一次int sum=a+b;            //执行一次printf("&d\n",sum);      //执行一次

上述程序段有4行代码,每一行执行1次,加起来一共执行了4次,f(n)=4,即T(n)=O(4)。根据推导方法中的第一条,将常数项以1代替。在保留其最高阶项时,发现其没有最高阶项,因此该算法的时间复杂度为O(1),为常数阶。程序段2代码如下所示:

void func()
{int i,sum=0;                         //执行一次for (i=0;i<=100;i++){sum +=i;                              //执行n次}printf("sd\n",sum);               //执行一次
}

该程序段的执行次数为1+n+1,则f(n)=n+2,即T(n)=O(n+2)。然后将常数项以1替换,且只保留最高阶项,则得出T(n)=O(n),因此该算法的时间复杂度为O(n),为线性阶。

程序段3代码如下所示:

void func()
{int i=l;do{i*=2}while (i<n);
}

在这个程序段中,当i<n时,循环结束。如果循环了f(n)次,则2(fn)=n,即f(n)=log2n,T(n)=O(log2n)。然后消除常系数,保留最高阶项,最后得出T(n)=O(logn),为对数阶。

用大O阶来推导算法的复杂度并不难,读者在以后的学习中设计算法,就可以用此法来估测算法的优劣。

2.空间复杂度

空间复杂度是对一个算法在运行过程中所占存储空间大小的度量,一般也作为问题规模n的函数,以数量级形式给出,格式如下所示:

1653992397625_43.png

一个算法的存储量包括输入数据所占空间、程序本身所占空间和辅助变量所占空间。在对算法进行分析时,只考虑辅助变量所占空间。若所需辅助空间相对于输入数据量来说是常数,则称此算法为原地工作。若所用空间量依赖于特定的输入,则除了有特殊说明外,均按最坏情况考虑。

有时候,在写代码时可以用空间来换取时间,例如,写一个算法来判断某年是否是闰年,这样每输入一个年份都要调用算法去判断一下,在时间上就有点复杂。为了提高效率,可以用空间来换取时间,即建立一个大小合适的数据,编号从0到n,如果是闰年,则存入数据1,否则存入数据0。这样只要通过判断年份编号上存储的是0还是1就知道该年份是否是闰年了。

用空间换取时间可以将运算最小化,但这两种情况哪种更好,要结合具体情况而定。一般情况下,都是用时间复杂度来度量算法,当不加限定地使用“复杂度”这一术语时,都是指时间复杂度。

http://www.lryc.cn/news/97088.html

相关文章:

  • 【问题记录】Ubuntu 22.04 环境下,打开 VS Code 老是访问密钥环该怎么解决?
  • format格式化输出语法详解
  • RocketMQ教程-(5)-功能特性-事务消息
  • HANA学习笔记
  • VMware虚拟机无法上网的解决办法
  • PLC-Recorder的高速采集有多快?0.5ms算快吗?看控制器能力了!
  • KMP算法总结
  • 消息中间件ActiveMQ介绍
  • 【100天精通python】Day9:数据结构_字典、集合
  • 上海VR全景展示,快速了解VR全景拍摄
  • VScode远程不用再输入密码操作
  • MyBatis基本用法-@TableId
  • React AntDesign写一个导出数据的提示语 上面有跳转的路径,或者点击知道了,关闭该弹层
  • 小红书课程发光社群知识库,点亮哥专为超级个体设计解决方案
  • 基于SpringBoot+Vue的摄影跟拍预定管理系统设计与实现(源码+lw+部署文档等)
  • HCIA 第二课总结
  • linux-------联网下载文件和配置
  • 字典树Trie
  • 算法之桶排序算法
  • 读kafka生产端源码,窥kafka设计之道(下)
  • Pytorch个人学习记录总结 06
  • Rust之泛型、特性和生命期(四):验证有生存期的引用
  • kubesphere安装中间件
  • zookeeper学习(二) 集群模式安装
  • 选择合适的图表,高效展现数据魅力
  • springboot自动装配
  • python小记-队列
  • SpringBoot——持久化技术
  • Kafka 入门到起飞 - 生产者参数详解 ,什么是生产者确认机制? 什么是ISR? 什么是 OSR?
  • 【文献分享】比目前最先进的模型轻30%!高效多机器人SLAM蒸馏描述符!