时间复杂度和空间复杂度的七七八八

news2024/11/18 11:20:41

文章目录

  • 时间空间复杂度
    • 1. 时间空间复杂度的重要性(作用)
    • 2. 时间复杂度和大O表示法
      • 1)算法图解
      • 2)代码随想录
      • 3)王道《数据结构》
    • 3. 大O指的是最糟的情形和一般的情形
      • 1)大O表示的是一般情况,并不是严格的上界
      • 2)王道中对三个维度的时间复杂度的解释:
    • 4. 常见的大O运行时间及化简规则
      • 1)常见渐进复杂度排序:
      • 2)分析程序复杂性,化简规则:
      • 3)大O可以省略常数项系数的原因
      • 4) 复杂度化简的例子
    • 5. 空间复杂度
      • 1)代码随想录
      • 2)王道数据结构
    • 6. O(logn)的解读

算法是一组完成任务的指令。任何代码片段都可视为算法。——《算法图解》

特别说明:文章是整理的笔记加自己汇集的资料及理解,参考自代码随想录、王道《数据结构》、《算法图解》(最近跟着carl哥准备刷题了,会坚持更新,争取早日养成输出的习惯)

时间空间复杂度

1. 时间空间复杂度的重要性(作用)

即使我们知道CPU运行一个程序所需的时间不只是算法执行的时间,比如

  • CPU执行每条指令所需的时间实际上并不相同,例如CPU执行加法和乘法操作的耗时实际上都是不一样的。
  • 现在大多计算机系统的内存管理都有缓存技术,所以频繁访问相同地址的数据和访问不相邻元素所需的时间也是不同的。
  • 计算机同时运行多个程序,每个程序里还有不同的进程线程在抢占资源。

尽管影响的因素甚多,但至少我们对自己写的程序的运行时间有个大体的评估。总不能写个查询人都反应过来了,程序还在执行中吧。

算法4中提到:

  • 火箭科学家需要大致知道一枚试射火箭的着陆点是在大海里还是在城市中;
  • 医学研究者需要知道一次药物测试是会杀死还是会治愈实验对象;

所以任何开发计算机程序员的软件工程师都应该能够估计这个程序的运行时间是一秒钟还是一年。

事实上抛开电脑的硬件配置,评估我们写的每一段程序好与差,最重要的还是时间和空间复杂度。 引用王道《数据结构》中的一句话,算法效率的度量是通过时间复杂度和空间复杂度来描述的。

2. 时间复杂度和大O表示法

先上结论,后边依次给出三个地方对时间复杂度的理解

  • 算法的速度指的并非时间,而是操作数的增速
  • 当讨论算法的速度时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加
  • 算法的运行时间用大O表示法表示

1)算法图解

最喜欢《算法图解》中给出的解释:大O表示法指出算法的速度有多快,即大O表示法让你能够比较操作数,指出了算法运行时间的增速

即大O解决两个问题:一是估计当前问题规模n下的运行时间,二是估计出随问题规模n的增大,算法运行时间的增速的变化

举一个书中的列子:Bob为NASA编写一个查找算法,此算法在火箭即将登陆月球前执行,帮助计算登陆地点,时间需10秒内(简单算法和二分查找中选一个)。

测试时列表中有100个元素(假设查一个元素需1毫秒,默认有序),简单查找需100毫秒,二分查找需7毫秒。而实际中了包含10亿个元素,10亿元素查询时二分查找运行时间30毫秒(log2(1000000000)约为30)。

但Bob根据100个元素得出的结论,二分查找的速度约为简单查找的15倍,10亿个元素简单查找为30*15=450毫秒,同时简单查找编写简单bug率低,Bob毅然选择简单查询。

实际上,10亿量级时最坏时间复杂度需10亿毫秒(整整11天啊!)。

Bob会简单的认为二分查找的速度约为简单查找的15倍本质原因:评价算法时只用了运行时间来衡量,这是没有意义的。

同一个问题,用同一种算法,由于问题规模的不同,首先时间是不同的,重要的是时间的增长速度也不同。所以评价算法的快慢用时间衡量没有意义,选择将算法需要执行的操作次数表示为问题规模n的函数,既可以通过输入规模n得出运行时间,也可以通过分析函数表达式本身的性质发现运行时间增速的变化。

贴出简单查询和二分法的时间复杂度函数
在这里插入图片描述

2)代码随想录

时间复杂度是一个函数,它定性描述该算法的运行时间。

如何估算算法的运行时间?
通常估算算法的操作单元数量来代表程序消耗的时间(默认CPU的每个单元运行消耗的时间都相同)。

假设算法的问题规模为n,那么操作单元数量便用函数f(n)来表示,随着数据规模n的增大,算法执行时间的增长率和f(n)的增长率相同,这称作为算法的渐近时间复杂度,简称时间复杂度,记为 O(f(n))

3)王道《数据结构》

一个语句的频度是指该语句在算法中被重复执行的次数。而算法中所有语句的频度之和记作T(n),即该算法问题的规模n的函数

时间复杂度是分析T(n)函数的数量级,算法中的基本运算(最深层循环内的语句)的频度f(n)与T(n)同数量级,所以算法的时间复杂度记为:T(n) = O(f(n))(‘O’的含义是T(n)的数量级)

3. 大O指的是最糟的情形和一般的情形

1)大O表示的是一般情况,并不是严格的上界

算法导论给出的解释:大O用来表示上界的,当用它作为算法的最坏情况运行时间的上界,就是对任意数据输入的运行时间的上界。

算法图解中也有提到:大O说的是最糟的情形。

用算法导论中给出的例子:插入排序的时间复杂度我们通常都说是O(n^2) 。

输入数据的形式对程序运算时间是有很大影响的,在数据本来有序的情况下时间复杂度是O(n),但如果数据是逆序的话,插入排序的时间复杂度就是O(n^2) ,也就对于所有输入情况来说,最坏是O(n^2) 的时间复杂度,所以称插入排序的时间复杂度为O(n^2)。

同样的同理再看一下快速排序,都知道快速排序是O(nlogn),但是当数据已经有序情况下,快速排序的时间复杂度是O(n^2) 的。

所以严格从大O的定义来讲,快速排序的时间复杂度应该是O(n^2)。但是我们依然说快速排序是O(nlogn)的时间复杂度。

这个就是业内的一个默认规定,这里说的O代表的就是一般情况,而不是严格的上界。

2)王道中对三个维度的时间复杂度的解释:

最坏时间复杂度: 指最坏情况下,算法的时间复杂度
平均时间复杂度 指所有可能输入实例在等概率出现的情况下,算法的期望运行时间。
最好时间复杂度 指在最好情况下,算法的时间复杂度。

4. 常见的大O运行时间及化简规则

  • O(log2(n)): 也叫对数时间,算法包括二分查找。
  • O(n): 也叫线性时间,算法包括简单查找。
  • O(n*logn): 算法包括快速排序,速度比较快的排序。
  • O(n^2): 算法包括选择排序,速度比较慢的排序。
  • O(n!): 算法包括旅行商问题,一种非常慢的算法。

图片来自算法图解,方便理解增速
图片来自算法图解

1)常见渐进复杂度排序:

O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(nlogn)线性对数阶 < O(n^2)平方阶 < O(n^3)立方阶 < O(n!)n的阶乘 < O(2^n)指数阶

2)分析程序复杂性,化简规则:

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

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

*注:化简例子在下一个大标题下

3)大O可以省略常数项系数的原因

附上代码随想录中的一个举例,如图是不同算法的时间复杂度在不同数据输入规模下的差异。
在这里插入图片描述
通常要决定使用哪种算法时,并不仅仅只考虑时间复杂度,也需要考虑数据规模。

如果数据规模很小甚至可以用O(n^2)的算法比O(n)的更合适(在有常数项的时候)。

比如上图中 O(5n^2) 和 O(100n) 在n为20之前很明显 O(5n^2)是更优的,所花费的时间也是最少的。

但O(100n) 就是O(n)的时间复杂度,O(5n^2) 就是O(n^2)的时间复杂度,为什么要默认O(n) 优于O(n^2) 呢?

这是因为大O就是数据量级突破一个点且数据量级非常大的情况下所表现出的时间复杂度,这个数据量也就是常数项系数已经不起决定性作用的数据量。

例如上图中20就是那个点,n只要大于20 常数项系数已经不起决定性作用了。

所以我们说的时间复杂度都是省略常数项系数的,是因为一般情况下都是默认数据规模足够的大, 基于这样的事实,给出的算法时间复杂的的一个排行如下所示:

O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(nlogn)线性对数阶 < O(n^2)平方阶 < O(n^3)立方阶 < O(n!)n的阶乘 < O(2^n)指数阶

但是也要注意大常数,如果这个常数非常大,例如10^7 ,10^9 ,那么常数就是不得不考虑的因素了。

4) 复杂度化简的例子

示例:O(2n^2 + 10n + 1000)

1)去掉运行时间中的加法常数项 (因为常数项并不会因为n的增大而增加计算机的操作次数)
O(2n^2 + 10n)

2)去掉常数系数(上文中已经详细讲过为什么可以去掉常数项的原因)
O(n^2 + n)

3)提取n的操作,变成O(n(n+1)) ,省略加法常数项后也就别变成了:
O(n^2)

5. 空间复杂度

1)代码随想录

定义: 空间复杂度(Space Complexity)记作S(n) 依然使用大O来表示,是对一个算法在运行过程中占用内存空间大小的量度,记做 S(n)=O(f(n))。

作用: 利用程序的空间复杂度,可以对程序运行中需要多少内存有个预先估计。

注意: 空间复杂度只是预先大体评估程序内存使用的大小,不能准确评估。毕竟很多因素会影响程序真正内存使用大小,例如编译器的内存对齐,编程语言容器的底层实现等等这些都会影响到程序内存的开销

空间复杂度O(1): 随n的变化,所需开辟的内存空间并不会随n的变化而变化。即此算法空间复杂度为一个常量,所以表示为O(1)。在王道数据结构中称此为算法原地工作(即指所需辅助空间是常量)

int j = 0;
for (int i = 0; i < n; i++) {
    j++;
}

空间复杂度为O(n): 当消耗空间和输入参数n保持线性增长,这样的空间复杂度为O(n)

int[] a = new int[n] //随着n的增大,开辟的内存大小呈线性增长,即 O(n)
for (int i = 0; i < n; i++) {
    a[i] = i;
}

2)王道数据结构

算法的空间复杂度S(n),定义为该算法所耗费的存储空间,它是问题规模n的函数。

渐进空间复杂度简称为空间复杂度。记作S(n) = O(g(n))。这里的g(n) 同代码随想录在空间复杂度给出的f(n)一样,都为程序语句关于n所占存储空间的函数。

6. O(logn)的解读

通常我们所说的算法的时间复杂度是logn不一定只是log 以2为底n的对数,可以是以10为底n的对数,也可以是以20为底n的对数,但我们统一说 logn,也就是忽略底数的描述。

如下图解释(图片截与代码随想录):
在这里插入图片描述
假如有两个算法的时间复杂度,分别是log以2为底n的对数和log以10为底n的对数,因为以2为底n的对数 = 以2为底10的对数 * 以10为底n的对数。(下方贴出了推到过程)

而以2为底10的对数是一个常数,在上文已经讲述了我们计算时间复杂度是忽略常数项系数的。

抽象一下就是在时间复杂度的计算过程中,log以i为底n的对数等于log 以j为底n的对数,所以忽略了i,直接说是logn。

这就是为什么时间复杂度logn可以忽略底数描述了。

补充解释第二个对数公式成立推导:
在这里插入图片描述

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

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

相关文章

算法修炼之练气篇——练气四层

博主&#xff1a;命运之光 专栏&#xff1a;算法修炼之练气篇 前言&#xff1a;每天练习五道题&#xff0c;炼气篇大概会练习200道题左右&#xff0c;题目有C语言网上的题&#xff0c;也有洛谷上面的题&#xff0c;题目简单适合新手入门。&#xff08;代码都是命运之光自己写的…

创建虚拟目录和用户访问控制+虚拟目录

目录标题 虚拟目录配置文件创建配置文件对应的目录资源在创建一个虚拟目录的配置文件 用户访问控制虚拟目录创建用户访问控制权限创建配置文件中的用户资源测试tom用户测试zhangsan用户 虚拟目录 Alias 虚拟目录名称 真是目录路径为了方便对于网站资源进行灵活管理&#xff0c…

使用 MVC 模式,实现简单登录功能 (Kotlin)

先放效果图&#xff1a; 第一张是登录页面效果图。用户输入登录名和密码&#xff0c;经过后台的非空验证和固定值验证&#xff0c;跳转到首页 第二张是首页效果图。用户点击 “update” 显示用户名和密码 这里的用户名和密码是后台设置的固定值&#xff0c;整体的登录逻辑特别…

python+opencv图像形态变换

形态变换主要用于二值图像的形状操作&#xff0c;形态变换的实现原理基于数字形态学。数字形态学也称形态学&#xff0c;它主要从图像内部提取信息来描述图像形态。形态学广泛应用于视觉检测、文字识别、医学图像处理、图像压缩编码等。形态变换主要包括腐蚀、膨胀和高级形态操…

Linux aarch64架构中使用docker安装mysql8

Linux aarch64架构中使用docker安装mysql8 1、遇到问题&#xff1a; 官网下载mysql包&#xff0c;安装完成后&#xff0c;启动mysql一直显示-bash: ./mysqld: 无法执行二进制文件。 网上找了各种资料&#xff0c;但是都没有作用&#xff0c;怀疑自己操作姿势不正确&#xff…

面试题集合

Dubbo是Alibaba开源的分布式服务框架&#xff0c;它最大的特点是按照分层的方式来架构&#xff0c;使用这种方式可以使各个层之间解耦合&#xff08;或者最大限度地松耦合&#xff09;。 从服务模型的角度来看&#xff0c;Dubbo采用的是一种非常简单的模型&#xff0c;要么是提…

DNS:DNS域名解析过程及原理

一、理解IP和域名 我们首先要了解域名和IP地址的区别。 IP地址是互联网上计算机唯一的逻辑地址。 通过IP地址实现不同计算机之间的相互通信&#xff0c;每台联网计算机都需要通过IP地址来互相联系和分别。 但由于IP地址是由一串容易混淆的数字串构成&#xff0c;人们很难记忆所…

C基础 --- 因为整型提升导致的BUG

为什么会做整型提升 通常情况下&#xff0c;在对int类型的数值作运算时&#xff0c;CPU的运算速度是最快的。在x86上&#xff0c;32位算术运算的速度比16位算术运算的速度快一倍。C语言是一个注重 效率的语言&#xff0c;所以它会作整型提升&#xff0c;使得程序的运行速度尽可…

基于ChatGPT AI自动产生Shader,AI自动产生AICommand

AIEngine 基于ChatGPT AI自动产生Shader 代码地址&#xff1a;https://github.com/ManoKing/AIEngine 使用方法&#xff1a; 1&#xff0c;打开 Window/Package Manager 2&#xff0c;选择 /Add package from git URL… 3&#xff0c;添加URL: https://github.com/ManoKing/…

VMware Aria Automation Orchestrator 8.12 - 现代工作流程自动化平台

VMware Aria Automation Orchestrator 8.12 - 现代工作流程自动化平台 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-aria-automation-orchestrator/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 现代工作流程…

民谣女神唱流行,基于AI人工智能so-vits库训练自己的音色模型(叶蓓/Python3.10)

流行天后孙燕姿的音色固然是极好的&#xff0c;但是目前全网都是她的声音复刻&#xff0c;听多了难免会有些审美疲劳&#xff0c;在网络上检索了一圈&#xff0c;还没有发现民谣歌手的音色模型&#xff0c;人就是这样&#xff0c;得不到的永远在骚动&#xff0c;本次我们自己构…

艺术家林曦老师新书《无用之美》即将发售,其中甘美提前与君共享~

十多年前&#xff0c;艺术家林曦老师做了一次主题为“无用之美”的演讲&#xff0c;从那时到现在&#xff0c;也一直教授着以“美”为核心的课程。经过十年的教学、和糯糯小朋友的相处&#xff0c;林曦老师觉得自己对这个主题有了更多的感触。      “有用的世界”繁复疲惫…

科技云报道:Serverless或许没有你想象中的安全

科技云报道原创。 随着云计算技术的进一步成熟&#xff0c;Serverless已成为引领云计算下一个十年的技术热点。 Serverless能够帮助开发者无需关注服务器、按照实际使用付费且可以享受服务自动弹性伸缩&#xff0c;将更多的精力放到业务逻辑本身。据Gartner预测&#xff0c;2…

Swift AsyncThrowingStream 和 AsyncStream Demo 演示

文章目录 前言什么是 AsyncThrowingStream&#xff1f;调整现有代码以使用流什么是 AsyncStream?AsyncThrowingStreamAsyncThrowingStream 迭代调试 AsyncStream取消一个 AsyncStream结论 前言 AsyncThrowingStream 和 AsyncStream 是 Swift 5.5 中由 SE-314 引入的并发框架的…

JUC并发编程15 | Java内存模型JMM与volatile

尚硅谷&#xff08;56-70&#xff09; JMM 引入一些大厂的面试题 Java内存模型JMM是什么JMM与volatile之间的关系是什么JMM有哪些特性or它的三大特性是什么为什么要有JMM&#xff0c;它为什么出现&#xff1f;功能和作用是什么&#xff1f;happens-before 先行发生原则是什么…

LaTeX极简入门

​LaTeX是什么&#xff1f; LaTeX是一种基于ΤΕΧ的排版系统&#xff0c;由美国计算机学家莱斯利兰伯特&#xff08;Leslie Lamport&#xff09;在20世纪80年代初期开发。 LaTeX是一款开源免费&#xff0c;并且应用相当广泛的排版工具。不但能够对文字、公式、图片进行精确而复…

电容笔和触控笔有什么区别?电容笔牌子排行榜

而现在&#xff0c;在无纸化教育的大热之下&#xff0c;电容笔这个配件&#xff0c;也被很多人所关注。许多人对电容笔与触控笔的不同之处感到困惑&#xff0c;事实上&#xff0c;这二者是非常容易分辨的&#xff0c;电容笔是适用在我们最常见的电容屏上才能进行操作&#xff0…

算法工程师面试题

1.关于边缘提取的算法有那些&#xff1f;各有什么优缺点&#xff1f; Canny算法&#xff1a;Canny算法是一种经典的边缘检测算法&#xff0c;具有较高的准确性和良好的鲁棒性。该算法利用高斯滤波器对图像进行平滑处理&#xff0c;然后计算图像中每个像素的梯度和方向&#xff…

TinyHttpd 运行过程出现的问题

最近拉了个 TinyHttpd 的工程下来&#xff0c;不过好像各个都有些改动&#xff0c;最后挑了篇阅读量最多的。工程也是从这里面给的链接下载的。 参考自&#xff1a;https://blog.csdn.net/jcjc918/article/details/42129311 拿下来在编译运行前&#xff0c;按这里说的&#x…

词云图制作(R)

词云图制作 文章目录 词云图制作[toc]1 工作准备2 实际操作 1 工作准备 材料准备&#xff1a; 文本数据txt文件&#xff0c;或者其他文本文件。R语言软件 2 实际操作 第一步&#xff1a;从网上相关新闻网站复制粘贴或下载相关文本数据&#xff0c;转化为txt格式文件或其他&…