时间复杂度和空间复杂度

  • 一.时间复杂度
    • 1.定义
    • 2.三种时间复杂度
    • 3.计算
      • *计算
        • #计算步骤
        • #常用技巧
        • #例题解析
  • 二.空间复杂度
    • #定义
      • *计算
        • #计算步骤
        • #常用技巧
        • #例题解析

一.时间复杂度

1.定义

定义:所有语句频度之和,记为T(n)。一个语句频度是指该语句在算法中被重复执行的次数。
T(n)是算法中问题规模的函数,时间复杂度主要分析T(n)数量级。
同通常采用算法中基本运算频度f(n)来分析算法时间复杂度。取f(n)中随n增长最快的项。
算法时间复杂度记为T(n)=O(f(n))。
理解T(n)=O(f(n)):O(f(n))表示取f(n)的同阶无穷小。f(n)的同阶无穷小就是取函数每项对比之后阶数最高的。
为什么要这么取呢?时间复杂度是大概描述算法效率,不需要多精确,所以,计算的时候直接取函数中阶数最高的部分,其余部分忽略不计。

2.三种时间复杂度

最坏时间复杂度:考虑输入数据最坏的情况
平均时间复杂度:考虑所有输入数据等概率出现的情况。
最好时间复杂度:考虑输入数据最好的情况。

3.计算

*计算

若语句执行次数是一个常数,则时间复杂度为O(1)。

下面是针对语句执行次数不是常数。

#计算步骤

  1. 找基本操作 :就是找最深层循环。
  2. 找问题规模n:出现在控制循环的条件中 ,问题规模n限制循环上限。
  3. 找控制循环的变量 i,分析循环变量的变化量。
  4. 根据2和3步骤分析基本操作执行次数x与问题规模n的关系f(n)=x。
  5. 取x的数量级O(x)(或者Of(n))就是算法时间复杂度T(n)。

【做题做熟悉了,一般把第三步和第四步合在一起,直接分析问题规模 n 和循环次数 x 的关系式。】

#常用技巧

*加法规则:

O(f(n))+ O(g(n)) = O(max(f(n),g(n)));
该方法出现在“语句块 一个模块一个模块”的情况。

*乘法规则:

O(f(n))*O(g(n)) = O((f(n)*g(n)));
该方法出现在“语句嵌套”和“函数递归调”用中。但不是所有嵌套语句都适用。

*常见的渐进时间复杂度:

O(1) < O(log2 n) < O(n) <O(n*log2 n) <O(n2) <O(n3) <O(2n) <O(n!) <O(nn)

#例题解析

上例题:


第一道例题

void fun(int n)
{int i = 1;
while(i <= n)
{i = i * 2;
}
}

第一步:找基本操作
便是语句 while循环

第二步:找问题规模
问题规模出现在条件 i <= n 中,那就是n。

第三步:找循环控制的变量 i 。
i每循环一次都要在自身乘以2。每次循环 i 值变化:2 4 8 16 ………。设循环x 次,则这里可以写出关于 i 的变化值与循环次数的函数 i = 2x

第四步:建立循环次数 x 与 问题规模n的关系。
因为i <= n,根据第三步建立关系 2x= n ;
解得 x =log2 n。

第五步:取数量级
O(x)= log2 n。
则时间复杂度T(n) = log2 n。


第二道例题:

int m = 0,i,j;
for(i = 1;i <= n;i++)        //第一层for(j = 1;j <= 2*i ;j++) //第二层m++;

嵌套语句从外层往内层分析
先分析第一层(虽然一眼看出来,但是还是浅浅分析一下)

for(i = 1;i <= n;i++)

第一步:找基本操作
那就是这个两层的嵌套循环。
【插入一个额外值得注意的,为什么要说找最深层循环,当在程序中出现多个语句模块时,就要把每个模块都计算相加,就比较费时间,对比一下语句模块,谁嵌套层数越多就越复杂,计算最复杂的,也就所说的找最深层循环,定位到最复杂的语句模块后,分析嵌套时就不用再进行第一步,每层直接从找问题规模开始】

第二步:找问题规模n
问题规模出现在条件 i <= n 中,那就是n。

第三步:找循环控制的变量 i 。
i 初始值为 1,i 增量为 1 ,设循环次数为 x1 则没次循环 i 与x1 的关系为 i = x1

第四步:建立循环次数 x 与 问题规模n的关系。
因为i <= n,根据第三步建立关系 x1 = n ;

分析第二层:

for(j = 1;j <= 2*i ;j++)

1.找问题规模n
该语句中问题规模为 2 * i ,(当我们第二层循环的问题规模与第一层相关联时,外层乘以内层循环计算时间复杂度是不可行的,我们应该回到时间复杂度的定义即语句执行的次数)每执行一次第一层循环,第二层循环问题规模变化 :2 ,4,6,8… ;

2.找控制循环的变量
该语句控制循环的变量为 j ,增量为1,那么内层循环结束语句执行次数可用下列式子表示:

综合分析取数量级
综合内外层外层循环结束语句执行次数可用下列式子表示:

语句执行次数为 f(n) = n2 +n;
T(n) = O(f(n)); T(n) = n2;


插入一道类似的题:

int m = 0,i,j;
for(i = 1;i <= n;i*=2)        //第一层for(j = 1;j <= i ;j++) //第二层m++;

分析第一层:

for(i = 1;i <= n;i*=2)

第一步直接略过到第二步。
第二步:找问题规模n
问题规模出现在条件 i <= n 中,那就是n。

第三步:找循环控制的变量 i
i 初始值为 1,i 增量为自身乘以2 ,变化为 1,2,4,8,16…,按照 i=2x-1 变化,设循环次数为 x 则没次循环 i 与x 的关系为 i=2x-1 变化。

第四步:建立循环次数 x 与 问题规模n的关系。
因为i <= n,根据第三步建立关系 i = n ;故 2x-1 = n ;x = log2n +1;1忽略不计。
故 x = log2n

分析第二层:

for(j = 1;j <= i ;j++)

1.找问题规模n
该语句中问题规模为 i ,第二层循环问题规模变化由第一层对 i 的分析可知 i=2x-1

2.找控制循环的变量
该语句控制循环的变量为 j ,增量为1,那么内层循环结束语句执行次数可用下列式子表示:

综合分析取数量级
综合内外层外层循环结束语句执行次数可用下列式子表示:

语句执行次数为f(n) = 2*n-1;
T(n) = O(f(n)); T(n) = n;【注意注意:系数也是不计的】


第三道列题

int fact(int n)
{if(n <= 1 )
return 1;
return n * fact(n-1);
}

【对于函数的递归调用,问题规模定位在传入的参数里,主要分析的是问题规模与函数调用次数的关系。再分析函数内部的时间复杂度,把内部时间复杂度与函数调用次数相乘,取数量级,就是该递归程序的时间复杂度。】

找问题规模n
问题规模在 int fact(int n) 中,则问题规模为 n。

调用次数 x 与问题规模 n的关系
问题规模变化量每次 n -1,题中条件语句n <= 1时,递归调用结束,则 x = n;

取数量级
函数内部时间复杂度为O(1) ,内部时间复杂度与函数调用次数相乘得到最后时间复杂度T(n) = n;

【个人小结:具体问题具体分析,再计算时间复杂度越来越熟练,直接分析问题规模 n 与执行次数 x 的关系。计算步骤适用于大部分程序。主要还是要抓住时间复杂度是语句执行的次数。】


二.空间复杂度

#定义

一个程序执行时所需要的存储空间来存放本身所用指令、常数、变量和输入数据外,还需要对一些数据进行操作的工作单元和存储实现计算机所需信息的辅助空间。

算法空间复杂度S(n) 为该算法消耗的存储空间。

首先,程序代码是固定不变的,不算进空间复杂度。
程序中那个部分能算进空间复杂度?
程序中数据部分算进空间复杂度。
数据:数据的初始化:如 int i; 整形的 i 占了四个字节,就是4b。

*计算

#计算步骤

第一步:找问题规模
第二步:找数据,分析占用空间与问题规模的关系。
第三步:取数量级

#常用技巧

*加法规则:

O(f(n))+ O(g(n)) = O(max(f(n),g(n)));
该方法出现在“不同的数据”的情况。
不同的数据,比如 int a,b; 这里把a 和 b 所占空间相加,a 和 b 是不同的
数据。

*乘法规则:

O(f(n))*O(g(n)) = O((f(n)*g(n)));
该方法出现在“二维数组”以上的数组。

*常见的渐进时间复杂度:

O(1) < O(log2 n) < O(n) <O(n*log2 n) <O(n2) <O(n3) <O(2n) <O(n!) <O(nn)

#例题解析

上例题:

【下面例题中会出现int i,i 占4B。根据不同的编译器,不同的数据类型占用空间是不一样的,在学习数据结构C语言版中,int 类型在C语言的内存中占四个字节,char 在C语言中占两个字节,为了方便理解,int i ,i 可以看为占了一个空间】


第一道例题:

void PRINT(int n)
{int i = 1;while(i <= n){i++;printf("第%d位选手");
}
}

第一步:找问题规模
代码中问题规模为 n

第二步:找数据,
代码中数据为 int i 。占了 4B 。

第三步:取数量级
无论问题规模怎么变,算法运行所需要的内存空间是固定的“常量”。常量都记作O(1)。所以 S(n) =O(1)


第二道例题:

void fun(int n)
{int s[n],k[n][n];
}

第一步:找问题规模
代码中问题规模为 n

第二步:找数据
代码中数据为 s[n],k[n][n]。f(n) 为 s 数组所占空间与 k 数组所占空间之和。
所以 f(n) = n2 + n 。

第三步:取数量级
f(n) = n2 + n ,S(n) =O(f(n)), 则S(n) = O(n2 )。


第三道例题

递归中的空间复杂度。
关于递归空间的调用,先了解函数调用栈。递归调用没有结束,空间不会被释放而是而是以栈的逻辑结构方式存在内存里,直到递归调用结束,空间才会释放。

void PRINT(int n)
{int a ,b ,c;if(n > 1){PRINT(n - 1);}printf("第%d位选手\n",n);
}

第一步:找问题规模
代码中问题规模为 n

第二步:找数据
代码中数据为 int a ,b ,c。每次递归调用都要占 12B, 调用递归 n 次 ,则空间复杂度为 n。

第三步:取数量级
由第二步可得 T(n) =O(n);


扩展

void PRINT(int n)
{int f[n];if(n > 1){PRINT(n - 1);}printf("第%d位选手\n",n);
}

第一步:找问题规模
代码中问题规模为 n

第二步:找数据
代码中数据为 int f[n] ,n 在递减,变化从 n ,n-1, n-2,…1。反过来 变化为 1,2,3,4…n -2,n-1,n;
第一次调用占n个空间,第二次调用占n-1个空间…最后一次调用占1个空间。是个等差数列,对这个等差数列求和得:g(n) = 1/2 * n2 + 1/2 * n;

第三步:取数量级
由第二步得关系:g(n) =1/2 * n2 + 1/2 * n; S(n) = O(g(n)), S(n) = O(n2)

【个人小结:具体问题具体分析,有些算法各层所需的存储空间不同,分析就略有区别。】

数据结构--时间复杂度计算和空间复杂度计算篇相关推荐

  1. 时间复杂度计算及空间复杂度计算

    目录 1.算法效率 2.时间复杂度 3.空间复杂度 4.大O渐进表示法 5.常见时间复杂度 常见复杂度对比 oj练习 1.算法效率 算法效率分析分为两种:第一种是时间效率,第二种是空间效率.时间效率被 ...

  2. 时间复杂度和空间复杂度计算(数据结构C语言实现1)

    写在前面 数据结构C语言系列,和博主一起学习简单的数据结构和算法,都是利用C语言实现,很基础,相信大家都能够学会,都有所收获.记得点赞,收获. 目录 写在前面 本节目标 基本概念 **常见算法的时间复 ...

  3. 数据结构-时间复杂度计算示例

    数据结构-时间复杂度计算示例 1 数据结构-第一章-思维导图 2 时间复杂度-简介 3 时间复杂度-示例 3.1 时间复杂度-常用技巧 3.2 时间复杂度-示例 3.2.1 对数阶-时间复杂度计算 3 ...

  4. 时间复杂度和空间复杂度计算

    目录 1.什么是时间复杂度和空间复杂度 1.1 时间复杂度 1.2 空间复杂度 2. 如何计算时间复杂度和空间复杂度 2.1 使用大O阶方法 2.2 计算一些常用算法的时间复杂度 2.3 计算一些常用 ...

  5. 空间复杂度计算超全整理!!(一起手撕复杂度计算

    承接上文:算法效率与时间复杂度(8条消息) 时间复杂度计算超全整理!!(数据结构和算法的第一步_vpurple__的博客-CSDN博客 目录 0.前言 1.空间复杂度 1.1 大O的渐进表示法 1.2 ...

  6. 浅淡数据结构时间复杂度和空间复杂度

    文章目录 前言 1.时间复杂度和空间复杂度的相关介绍 1.为什么要引入时间复杂度和空间复杂度的概念 2.什么是时间复杂度和空间复杂度 2.具体示例分析 1.大O法只保留高阶项 2.一般情况关注的是算法 ...

  7. 重学数据结构与算法(02)--将时间复杂度转换成空间复杂度

    将时间复杂度转换成空间复杂度 1)时间昂贵.空间廉价 2)数据结构连接时空 3)降低复杂度的案例 例一 例二 4)总结 面试的过程中,常常会遇到考察手写代码的场景,通常面试官会追问:"这段代 ...

  8. (二) 时间/空间复杂度计算

    时间/空间复杂度计算 时间复杂度是什么? O(1) O(n) O(1)+O(n)=O(n) O(n)*O(n)=O(n^2) O(logN) 空间复杂度是什么? O(1) O(n) O(n^2) 思考 ...

  9. 第2章 时间空间复杂度计算

    1时间复杂度计算 时间复杂度是什么? 一个函数,用大O表示,例如:O(1), O(N), O(logN). 定性描述算法的运行时间. 时间复杂度常见图: 案例: O(1) let i = 0 i += ...

最新文章

  1. Python.Paste指南之Deploy(1)-概念
  2. powerdesigner使用vba脚本创建物理模型的表和列
  3. 02 | Spring Data Common 之 Repository 如何全面掌握?
  4. 学习笔记之APACHE ANT
  5. linux桌面服务器系统下载,Ubuntu 14.10 中文桌面版/服务器正式版下载
  6. canvas绘制线条1像素的问题
  7. Python之数据分析(numpy中的多项式拟合)
  8. 为什么说干实业的玩不过干金融的?
  9. 创建和销毁对象(1)
  10. 第六周Java学习总结
  11. 3500份课程课后习题答案与大家分享~~
  12. epsonl360打印机连接电脑_epsonl360打印机脱机如何解决
  13. 史上最详细的梯度下降优化算法介绍(从SGD到Adam至Lookahead)
  14. 敏捷看板设计-项目集看板
  15. Peekaboo—站立式会议+alpha冲刺:Day3冲刺随笔
  16. mysql已启动但无法连接_MySQL无法正常启动,Navicat连接出错,解决2003问题
  17. UVA10306 - e-Coins(二维完全背包)
  18. JavaScript - 简介
  19. python自动化ppt_python自动化办公手册之python操作PPT
  20. 将mysql语句转换为sql_数据库-转换sql语句

热门文章

  1. Splunk简介及安装
  2. 将小写金额转换为中文大写
  3. JS键盘事件获取键盘码
  4. html怎么增加声音,HTML之声音标志
  5. 传感器 宽动态范围介绍
  6. 测试用例设计方法1——等价类
  7. 挑战程序设计竞赛书的题解总结(连载中)
  8. 用于处理机器学习大数据文件的7种方法
  9. win7下安装nodejs16+
  10. vue组件通信---全局事件总线(任意组件间通信)