浅析时间复杂度与空间复杂度

news2024/11/16 17:56:23

时间复杂度

何为时间复杂度

算法的时间复杂度,是一个用于度量一个算法的运算时间的一个描述,本质是一个函数,根据这个函数能在不用具体的测试数据来测试的情况下,粗略地估计算法的执行效率,换句话讲时间复杂度表示的只是代码执行时间随数据规模增长的变化趋势。在数据结构中,算法的时间复杂度常用大O来表述。

大O表示法

大O表示法是一种特殊的表示法,指出了算法的速度是属于哪一个数量级的。

大O表示法的数学语言描述如下:

算法的时间复杂度通常用大O符号表述,定义为T[n] = O(f(n))。称函数T(n)以f(n)为界或者称T(n)受限于f(n)。 如果一个问题的规模是n,解这一问题的某一算法所需要的时间为T(n)。T(n)称为这一算法的“时间复杂度”。当输入量n逐渐加大时,时间复杂度的极限情形称为算法的“渐近时间复杂度”。

简单来说就是一个程序执行次数的估计值是在哪一个数量级的,例如八种常见排序算法的时间复杂度复杂度如下:

分析算法时间复杂度的基本方法

首先找出计算语句执行次数的数量级,接着用大O表示法来表示

例如下面这个for循环的语句要执行n次(主要是里面的i<=n要执行n次),所以它的时间复杂度是O(n)

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

而下面这段代码的,第一个for循环的语句要执行n次(主要是里面的i<=n要执行n次),第二个for循环的语句要执行n次(主要是里面的j<=n要执行n次),所以它的时间复杂度是O(n^2)

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

特殊规则
1) 加法规则 
T(n,m) = T1(n) + T2(n) = O (max ( f(n), g(m) )

2) 乘法规则 
T(n,m) = T1(n) * T2(m) = O (f(n) * g(m))

3) 常量规则
在大O表示法里面有一个特例,如果T1(n) = O(c), c是一个与n无关的任意常数,T2(n) = O ( f(n) ) 则有
        T(n) = T1(n) * T2(n) = O ( c*f(n) ) = O( f(n) )

也就是说,在大O表示法中,任何非0正常数都属于同一数量级,记为O(1)。

时间复杂度分析示例

for(i=1;i<=n;i+ +)
   for(j=1j<=n;j++) {
       c[i][j]=0;
       for{k= =1:k<=n;k++)
          c[i]I[j]=c[i][j]+ a[i][k]*b[k][j]; 
}

时间复杂度:n*n*n=n3;


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

分析:

关键是要找出来执行次数x与n的关系,并表示成n的函数
若循环执行1次: i=1*2=2,
若循环执行2次: i=2*2=22(2的平方哈,下面依次)
若循环执行3次: i=2*2=23
.......
若循环执行x次: i=2x(2的x平方哈,下面依次)
又因为i要小于等于n
则2x<=n . 求出x<=log2n

所以时间复杂度为O(logN)

空间复杂度

何为空间复杂度

空间复杂度也是一个数学表达式,它是用来对算法在运行过程中临时占用存储空间大小的度量。

这里也有一个常见误区,空间复杂度并不是计算程序占用了多少字节的空间,这样做是意义不大的。所以空间复杂度计算的是变量的个数。同时间复杂度一样,空间复杂度也是采用的大O渐进表示法。

由于函数运行时所需要的栈空间(如存储参数、局部变量等)在预处理期间就已经确定好了,因此空间复杂度大多数是通过函数在运行时申请的额外空间来确定的。

空间复杂度分析示例

由于我们已经了解了时间复杂度,所以很多内容就不需要再赘述了,这里我们直接通过示例分析来理解空间复杂度的计算。


示例1

void BubbleSort(int* a, int n)
{
     assert(a);
     for (size_t end = n; end > 0; --end)
     {
         int exchange = 0;
         for (size_t i = 1; i < end; ++i)
         {
             if (a[i-1] > a[i])
         {
             Swap(&a[i-1], &a[i]);
             exchange = 1;
         }
     }
         if (exchange == 0)
             break;
     }
}

乍一看,有两个for循环,像是O(N^2)的空间复杂度,但其实不是,这里并没有使用的空间,只有线性(即常数级)的变量。所以这里的空间复杂度是O(N^2)。

也许看第一个示例还是云里雾里的,但不要在此纠结,继续看下面两个示例,会慢慢拨云见日的。


示例2

long long* Fibonacci(size_t n)
{
     if(n==0)
     return NULL;
 
     long long * fibArray = (long long *)malloc((n+1) * sizeof(long long));
     fibArray[0] = 0;
     fibArray[1] = 1;
     for (int i = 2; i <= n ; ++i)
     {
         fibArray[i] = fibArray[i - 1] + fibArray [i - 2];
     }
     return fibArray;
}

算法中额外开辟了N个空间(指的是malloc申请的空间),所以空间复杂度为O(N)


示例3

long long Fac(size_t N)
{
     if(N == 0)
     return 1;
 
     return Fac(N-1)*N;
}

算法中递归调用了N次,开辟了N个栈帧,每个栈帧中没有额外开辟空间,即空间复杂度为O(N)。

结果分析:

要注意,这里的空间复杂度与时间复杂度的理解上有些出入。虽然主观感觉这个函数是递归调用了O(2^N)次,应该是开辟2^N块空间,但实际上并不是,因为函数在调用时并不是一直在占用,所以当一个函数执行完毕后,栈帧销毁,这块空间就释放了,下一次递归时就相当于并没有使用更多的空间。所以相当于这里的空间复杂度就是,走到最深层递归调用所占用的空间。

所以相当于空间复杂度的求法是考虑所能使用的最大空间。而时间复杂度是,只要执行一次就将这次执行的时间算进去。所以可以这样来理解 “时间是一去不复返的,用了多少就算多少;空间是可以循环利用的;能用多少就算多少”。

常见的复杂度等级比较

下表是按照时间(空间)复杂度的执行时间(执行空间)从上到下依次递增。数据结构中log如果没有特殊说明一般都是默认以2为底的。

执行次数名称级别大O记法
c(c是常量) 常数级O(1)
logN对数级O(logN)
√N根号级O(√N)
log²N对数平方级O(log²N)
N线性级O(N)
NlogN线性对数级O(NlogN)
Nlog²N线性对数平方级O(N(log²N))
平方级O(N²)
立方级O(N³)
2ⁿ指数级O(2ⁿ)

最后

由于这块内容并不难,所以这里只是浅析一波,并没有过多的赘述。如有不足,还请及时指正,接受并感谢各方的意见与批评。

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

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

相关文章

GPT-4问世;LLM训练指南;纯浏览器跑Stable Diffusion

1.多模态GPT-4正式发布&#xff1a;支持图像和文本输入&#xff0c;效果超越ChatGPT OpenAI的里程碑之作GPT-4终于发布&#xff0c;这是一个多模态大模型&#xff08;接受图像和文本输入&#xff0c;生成文本&#xff09;。主要能力有&#xff1a; GPT-4可以更准确地解决难题&a…

【软件安装】图数据库_Neo4j下载与安装配置详解

【软件安装】图数据库_Neo4j安装下载详解 文章目录【软件安装】图数据库_Neo4j安装下载详解1. 前言2. 下载Neo4j3. 安装 配置3.1 解压3.2 配置4. 启动Neo4j5. 参考1. 前言 因为使用Neo4j时默认是需要java-jdk的支持&#xff0c;因此在下载neo4j之前&#xff0c;需要下载jdk&a…

7年,从功能测试到测试开发,我证明了自己

我感觉我是一个比较有发言权的人吧&#xff0c;我在测试行业爬模滚打7年&#xff0c;从点点点的功能测试到现在成为测试开发工程师&#xff0c;工资也翻了几倍&#xff1b; 个人觉得&#xff0c;测试的前景并不差&#xff0c;只要自己肯努力&#xff1b;我刚出来的时候是在鹅厂…

Android 高通Camera2 Camera Device Close

1、很多人看到这个日志第一感觉可能觉得哪里没有合理释放&#xff0c;于是带着这个思路去进行百度探索 2、一开始我去寻找 ImageReader.OnImageAvailableListener 这个问题 var afterBitmap: Bitmap? null/**监听拍照的图片 */private val imageAvailableListener ImageRead…

算法 贪心3 || 1005. K 次取反后最大化的数组和 134. 加油站 135. 分发糖果

1005. K 次取反后最大化的数组和 思路&#xff1a;给数组按照绝对值大小排序&#xff0c;优先将负数转成正数。如果此时 k % 2 1 。最后再将绝对值最小的值变成负数&#xff08;该值可能原本是负数&#xff09; 而不是直接从小到大排序。 例如-8&#xff0c;-5&#xff0c;-5…

Zebec Protocol 出席香港 Web3 峰会,带来了哪些信息?

梳理香港加密新政的细节&#xff0c;一个明确的脉络是&#xff0c;香港加密新政的整体目的是令虚拟资产交易明确化和合法化&#xff0c;通过不断完善的监管框架&#xff0c;促进香港虚拟资产行业的可持续和负责任地发展。 在加强合规和持牌经营的监管思路下&#xff0c;长期审…

JavaScript|JS修仙篇|一本就够了|笔记|(超详细|保姆级)

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;老茶icon &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开兴好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;计…

common markdown命令大全,控制文章格式

直接上教程 提到Markdown&#xff0c;很多人首先想到的是简单、Easy等等。的确&#xff0c;Markdown为简单而生。Markdown是由一个叫 JOHN GRUBER 的哥们发明的&#xff0c;它的语法用一篇文章就可以说完。不相信吗&#xff1f;让我们来试试看... 基础语法 标题 Markdown支持6…

搭建windows下基于VSCode的C++编译和调试环境

VSCode是目前比较流行的IDE&#xff0c;因为它插件丰富&#xff0c;依据需求扩展&#xff0c;非常方便。 本文记录搭建windows下基于VSCode的C编译和调试环境的过程。 网上关于此问题的帖子比较多&#xff0c;找了好几个也没有试验成功&#xff0c;最后发现还是按照VScode的官方…

揭秘阿里新大招:大模型只是前菜

技术的代际变革往往对商业格局产生深远影响。眼下&#xff0c;随着产业各界对大模型的投入布局加深&#xff0c;一个业界共识逐渐诞生&#xff1a;大模型正在改变云生态&#xff0c;将为云计算行业带来新的奇点。 在过去的一段时间里&#xff0c;市场研究机构IDC在2022年底的预…

Unity和Visual studio开发调试环境配置-工具插件安装和配置

在Unity开发中&#xff0c;常用C#脚本进行功能开发&#xff0c;需要用到Visual Studio进行开发和调试&#xff0c;需要分别在Unity3d和Visual Studio中安装插件和工具才能更好的进行开发和调试。 visual studio安装Unity扩展工具 visual studio中“工具”→“获取工具和功能”…

Leetcode.1019 链表中的下一个更大节点

题目链接 Leetcode.1019 链表中的下一个更大节点 Rating &#xff1a; 1571 题目描述 给定一个长度为 n 的链表 head 对于列表中的每个节点&#xff0c;查找下一个 更大节点 的值。也就是说&#xff0c;对于每个节点&#xff0c;找到它旁边的第一个节点的值&#xff0c;这个节…

[Python工匠]输出②数值与字符串

2.1 基础知识 2.1.1 数值基础 在Python中&#xff0c;一共存在三种内置数值类型&#xff1a;整型&#xff08;int&#xff09;、浮点型&#xff08;float&#xff09;和复数类型&#xff08;complex&#xff09;。 在大多数情况下&#xff0c;我们只需要用到前两种类型&#x…

SAR ADC系列23:异步SAR逻辑

异步sar逻辑的引入&#xff1a; 原因1&#xff1a;提高转换速度 ■ 同步时钟从第一个比较周期到最后一个比较周期长度都是相等的。对于Latch比较器&#xff0c;信号幅度越小&#xff0c;比较时间越长&#xff08;参考latch时域响应那一节&#xff09;。为了保证比较器…

Linux串口出厂测试工具与使用说明

1、说明 本文针对Linux系统上如何对各类串口硬件进行出厂测试进行硬件连接和软件使用说明&#xff0c;提供的软件测试工具wchsertest&#xff0c;适用于USB、PCI、PCIe转串口设备等、同样也适用于原生ttyS串口。 2、串口测试硬件连接 在测试前&#xff0c;需要制作单独的硬件…

寸照换底色技巧大全,超详细图文教程

在日常的设计工作中&#xff0c;我们常常需要将图片的背景色进行修改&#xff0c;以适应不同的场景和需求。其中最常用的方法就是寸照换底色技巧。本文将为大家介绍一些常见的寸照换底色技巧&#xff0c;并提供超详细的图文教程&#xff0c;帮助大家轻松完成这项任务。 一、使…

2023最新面试题-Java-6

1. Date API Java 8 在包java.time下包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多&#xff0c;但 又不完全一样&#xff0c;下面的例子展示了这组新API里最重要的一些部分&#xff1a; Clock类提供了访问当前日期和时间的方法&#xff0c;Clock是时区敏…

springboot加载命令行参数ApplicationArguments

往期文章 springcloud整合knike4j聚合微服务接口文档 spring源码 - 条件注解ConditionnalOnClass的原理分析 springboot项目实现导出pdf功能&#xff0c;这也太简单了吧 目录 文章目录往期文章目录一、介绍二、通过应用程序参数获取配置1. 通过bean获取应用程序参数2. 通过V…

在外web浏览器远程访问jupyter notebook服务器

文章目录前言视频教程1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口5. 固定公网地址转载自远控源码文章&#xff1a;公网远程访问jupyter notebook【cpolar内网穿透】 前言 Jupyter Notebook&#…

我现在必须new一个对象!!!

目录 前言 1.new 2.delete 3.底层逻辑 4.定位new 5.对比 前言 &#x1f383;之前在使用C语言的时候&#xff0c;我们便使用 malloc 和 calloc 等函数进行动态内存的开辟。但 C 之中又引入了两个操作符 new 和 delete 来代替C语言中的函数进行动态内存的管理。下面就一起…