时间复杂度空间复杂度怎么算?

什么是算法

算法的定义是这样的:解题方案的准确而完善的描述,是一系列解决问题的清晰指令。巴拉巴拉的,虽然是一小句但还是不想看(题外话:有时候吧专业名词记下来面试的时候还是挺有用的),其实就是解决一个问题的完整性描述。只不过这个描述就可能是用不同的方式或者说是“语言”了。

算法的效率

既然算法是解决问题的描述,那么就像一千个人眼中有一千个阿姆雷特他大姨夫一样,解决同一个问题的办法也是多种多样的,只是在这过程中我们所使用/消耗的时间或者时间以外的代价(计算机消耗的则为内存了)不一样。为了更快、更好、更强的发扬奥利奥..哦不,提高算法的效率。所以很多时候一个优秀的算法就在于它与其他实现同一个问题的算法相比,在时间或空间(内存)或者时间和空间(内存)上都得到明显的降低。

所以呢,算法的效率主要由以下两个复杂度来评估:

时间复杂度:评估执行程序所需的时间。可以估算出程序对处理器的使用程度。
空间复杂度:评估执行程序所需的存储空间。可以估算出程序对计算机内存的使用程度。

设计算法时,时间复杂度要比空间复杂度更容易出问题,所以一般情况一下我们只对时间复杂度进行研究。一般面试或者工作的时候没有特别说明的话,复杂度就是指时间复杂度。

 1.0 - 空间复杂度
一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。  
(1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。S(n)=O(f(n))  其中n为问题的规模,S(n)表示空间复杂度。

2.0 - 时间复杂度

接下来我们还需要知道另一个概念:时间频度。这个时候你可能会说:“不是说好一起学算法吗,这些东东是什么?赠品吗?”。非也非也,这是非卖品。

因为一个算法执行所消耗的时间理论上是不能算出来的,没错正是理论上,so我们任然可以在程序中测试获得。但是我们不可能又没必要对每个算法进行测试,只需要知道大概的哪个算法执行所花费的时间多,哪个花费的时间少就行了。如果一个算法所花费的时间与算法中代码语句执行次数成正比,那么那个算法执行语句越多,它的花费时间也就越多。我们把一个算法中的语句执行次数称为时间频度。通常(ps:很想知道通常是谁)用T(n)表示。

在时间频度T(n)中,n又代表着问题的规模,当n不断变化时,T(n)也会不断地随之变化。为了了解这个变化的规律,时间复杂度这一概念就被引入了。一般情况下算法基础本操作的重复执行次数为问题规模n的某个函数,用也就是时间频度T(n)。如果有某个辅助函数f(n),当趋于无穷大的时候,T(n)/f(n)的极限值是不为零的某个常数,那么f(n)T(n)的同数量级函数,记作T(n)=O(f(n)),被称为算法的渐进时间复杂度,又简称为时间复杂度

2.1 - 大O表示法

用O(n)来体现算法时间复杂度的记法被称作大O表示法

一般我们我们评估一个算法都是直接评估它的最坏的复杂度。

大O表示法O(f(n))中的f(n)的值可以为1、n、logn、n^2 等,所以我们将O(1)、O(n)、O(logn)、O( n^2 )分别称为常数阶、线性阶、对数阶和平方阶。下面我们来看看推导大O阶的方法:

推导大O阶

推导大O阶有一下三种规则:

  1. 用常数1取代运行时间中的所有加法常数
  2. 只保留最高阶项
  3. 去除最高阶的常数

举好多栗子

  • 常数阶
  • let sum = 0, n = 10; // 语句执行一次
    let sum = (1+n)*n/2; // 语句执行一次
    console.log(`The sum is : ${sum}`) //语句执行一次

     

这样的一段代码它的执行次数为 3 ,然后我们套用规则1,则这个算法的时间复杂度为O(1),也就是常数阶。

再例如:如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。
x=91; y=100;
while(y>0) if(x>100) {x=x-10;y–;} else x++;
解答: T(n)=O(1),
这个程序看起来有点吓人,总共循环运行了1000次,但是我们看到n没有?这段程序的运行是和n无关的,就算它再循环一万年,我们也不管他,只是一个常数阶的函数

  • 线性阶
let i =0; // 语句执行一次
while (i < n) { // 语句执行n次console.log(`Current i is ${i}`); //语句执行n次i++; // 语句执行n次}

这个算法中代码总共执行了 3n + 1次,根据规则 2->3,因此该算法的时间复杂度是O(n)。

  • 对数阶
let number = 1; // 语句执行一次
while (number < n) { // 语句执行logn次number *= 2; // 语句执行logn次
}

上面的算法中,number每次都放大两倍,我们假设这个循环体执行了m次,那么2^m = nm = logn,所以整段代码执行次数为1 + 2*logn,则f(n) = logn,时间复杂度为O(logn)。

  • 平方阶
for (let i = 0; i < n; i++) { // 语句执行n次for (let j = 0; j < n; j++) { // 语句执行n^2次console.log('I am here!'); // 语句执行n^2}
}

上面的嵌套循环中,代码共执行 2*n^2 + n,则f(n) = n^2。所以该算法的时间复杂度为O(n^2 )

例如:当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。
x=1;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
for(k=1;k<=j;k++)
x++;   
该程序段中频度最大的语句是(5),内循环的执行次数虽然与问题规模n没有直接关系,但是却与外层循环的变量取值有关,而最外层循环的次数直接与n有关,因此可以从内层循环向外层分析语句(5)的执行次数: 则该程序段的时间复杂度为T(n)=O(n3/6+低次项)=O(n3)

常见时间复杂度的比较

O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)

 

 

计算空间复杂度

首先要明确一个概念,变量的内存分配发生在定义的时候

 忽略常数,用O(1)表示 
递归算法的空间复杂度=递归深度N*每次递归所要的辅助空间 
对于单线程来说,递归有运行时堆栈,求的是递归最深的那一次压栈所耗费的空间的个数,因为递归最深的那一次所耗费的空间足以容纳它所有递归过程。
a = 0
b = 0
print(a,b)
它的空间复杂度O(n)=O(1);

def fun(n):
k = 10
if n == k:
return n
else:
return fun(++n)
递归实现,调用fun函数,每次都创建1个变量k。调用n次,空间复杂度O(n*1)=O(n)。

for(i=0;i<n;++):
temp = i
 变量的内存分配发生在定义的时候,因为temp的定义是循环里边,所以是n*O(1)

temp=0;
for(i=0;i<n;i++):
temp = i
temp定义在循环外边,所以是1*O(1) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/576457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么样的知识,值得我们终生学习

#什么样的知识&#xff0c;值得我们终生学习&#xff1f; 原文&#xff1a;https://dwz.cn/vylyXXJi 一、引言 可能你从初中就开始抱怨&#xff1a;我学相似三角形能干什么&#xff1f;阿伏伽德罗常数有什么用&#xff1f;我一不跳楼&#xff0c;二不高空抛物&#xff0c;学自由…

美团面试题:Hashmap的结构,1.7和1.8有哪些区别,深入的分析

&#xff08;一&#xff09; 真实面试题之&#xff1a;Hashmap的结构&#xff0c;1.7和1.8有哪些区别 不同点&#xff1a; &#xff08;1&#xff09;JDK1.7用的是头插法&#xff0c;而JDK1.8及之后使用的都是尾插法&#xff0c;那么他们为什么要这样做呢&#xff1f;因为JDK1…

作品展结束了,学习才真正的开始

我的作品展旅程分为两个大的部分。 一、班里的事务&#xff08;这是最重要&#xff0c;也最为艰巨的。&#xff09; 从4月15号自考结束后&#xff0c;开始真正进入作品展的筹划阶段。主要和唐欢负责作品的筛选工作&#xff0c;由于我工作经验有限&#xff0c;能力更是有限&…

数据结构第一章概论习题及答案

一、名词解释 1.数据表示 2.数据处理 3.数据 4.数据元素 5.逻辑关系 6.逻辑结构 7.结构 8.运算 9.基本运算 10.存储结构 11.顺序存储结构 12.链式存储结构 13.索引存储结构 14.散列存储结构 15.算法 16.运行终止的程序可执行部分 17.…

管理学习笔记(1)——高效团队的五大关键

高效团队的五大关键1. 安全感&#xff1a;敢于冒险&#xff0c;不会因此干到不安 2. 可靠性&#xff1a;指望他人可以准时完成高质量的工作 3. 结构与清晰度&#xff1a;目标、角色和执行计划都很清楚、明确 4. 工作意义&#xff1a;对各自来说做意义重大的工作 5. 工作影响…

算法导论-用于不相交集合的数据结构

21.2-4 对于图21-3中操作序列的运行时间&#xff0c;给出其紧确的渐近界。假定采用的是链表表示和加权合并启发式策略。 解&#xff1a;make-set&#xff0c;O(n)&#xff1b;加权合并启发&#xff0c;每次将较短链表链接到较长链表&#xff0c;即每次将长度为1的集合链接到另外…

大数据技术之 Kafka (第 3 章 Kafka 架构深入 ) Kafka 消费者

3.3.1 消费方式 consumer 采用 pull&#xff08;拉&#xff09;模式从 broker 中读取数据。 push&#xff08;推&#xff09;模式很难适应消费速率不同的消费者&#xff0c;因为消息发送速率是由 broker 决定的。 它的目标是尽可能以最快速度传递消息&#xff0c;但是这样很…

最活跃FPGA论坛推荐社区

http://forums.xilinx.com/ Xilinx User Community Forums(Xilinx用户交流社区)http://www.openhw.org/ 中国首个开放源码硬件社区http://xilinx.eetrend.com/ 电子创新网赛灵思中文社区http://bbs.elecfans.com/forum.php 电子发烧友社区&#xff08;电子技术论坛&#xff09;…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) offset讲解

新版的 Kafka 使用一个选举出来的 controller 来监听 zookeeper&#xff0c;其他 node 再去和 controller 通信&#xff0c;这么做的目的是为了减少 zookeeper 的压力。bootstrap-servers 会自动发现其他 broker&#xff0c;这也是 bootstrap 的含义 前面我们讲到了消费者&…

创建线程的三种方式

第一种&#xff0c;用Thread子类创建 Thread thread new Thread(){ Overridepublic void run() {while(true){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("1---->" Thread.currentThread().getName())…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) 消费者组案例

1&#xff09;需求&#xff1a;测试同一个消费者组中的消费者&#xff0c;同一时刻只能有一个消费者消费。 2&#xff09;案例实操 &#xff08;1&#xff09;在 backupo01、backupo02 上修改/usr/local/hadoop/kafka/kafka_2.12-2.4.1/config/consumer.properties 配置 文件…

Easyui弹出窗口在iframe中弹出被当前iframe遮罩的问题(解决方法)

例如我们点击一个按钮&#xff0c;然后弹出我们需要的Window控件窗口。 1 //点击按钮2 var _testWindow window.top.$(testWindow);3 $(#testButton).click(function(){4 if(_testWindow.length < 0) {5 _testWindow window.top.$("<div idtestWin…

JDK1.8中String类的intern()方法学习

jdk1.8字符串常量池是位于堆中&#xff1b; 在jdk1.8中使用如下指令时会同时在堆中和常量池&#xff08;前提是常量池中还没有该对象&#xff09;中创建字符串对象&#xff0c;但是s是指向堆中。 String s new String("HELLO"); 如下方法会判断常量池中是否存在s,…

sfs2x 连接 mongodb

void initMongodb() {Mongo mongo;try {trace("\ninitMongodb\n");mongo new Mongo("localhost", 10011);DB db mongo.getDB("yourdb");// 从Mongodb中获得名为yourColleection的数据集合&#xff0c;如果该数据集合不存在&#xff0c;Mongodb…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) 高效读写数据

1&#xff09;顺序写磁盘 Kafka 的 producer 生产数据&#xff0c;要写入到 log 文件中&#xff0c;写的过程是一直追加到文件末端&#xff0c; 为顺序写。官网有数据表明&#xff0c;同样的磁盘&#xff0c;顺序写能到 600M/s&#xff0c;而随机写只有 100K/s。这 与磁盘的机…

设计模式参考博客

http://www.cnblogs.com/zhenyulu/category/6930.html 吕震宇的博客园&#xff0c;关于设计模式介绍的比较全面。很值得学习的博客转载于:https://www.cnblogs.com/wangzihao/archive/2012/05/23/2514485.html

大数据技术之kafka (第 3 章 Kafka 架构深入) Zookeeper 在 Kafka 中的作用

Kafka 集群中有一个 broker 会被选举为 Controller&#xff0c;负责管理集群 broker 的上下线&#xff0c;所有 topic 的分区副本分配和 leader 选举等工作。 Controller 的管理工作都是依赖于 Zookeeper 的。 以下为 partition 的 leader 选举过程&#xff1a; Leader选举流…

SQLServer优化二

建立合理的索引,避免扫描多余数据&#xff0c;避免表扫描&#xff01;几百万条数据&#xff0c;照样几十毫秒完成查询。关于SQL查询效率&#xff0c;100w数据&#xff0c;查询只要1秒&#xff0c;与您分享&#xff01; 查询效率分析&#xff1a; 子查询为确保消除重复值&#x…

大数据技术之kafka (第 3 章 Kafka 架构深入) Kafka 事务

Kafka 从 0.11 版本开始引入了事务支持。事务可以保证 Kafka 在 Exactly Once 语义的基础上&#xff0c;生产和消费可以跨分区和会话&#xff0c;要么全部成功&#xff0c;要么全部失败 3.6.1 Producer 事务 为了实现跨分区跨会话的事务&#xff0c;需要引入一个全局唯一的 T…

JasperReport里面的Demo

1. alterdesign 该例子演示了报表编译后&#xff0c;在报表展现的时候如何动态的控制其中的元素比如让某一个矩形变色或其他 2. antcompile 演示如何让 ant 来编译 3. chart 演示了如何在报表中添加图像&#xff0c;JasperReport是用Scriptlet的方式往报表中添加图像&#xff0…