时间和空间复杂度分析

前言

对于数据结构相关的博客文章,我是根据大学本科阶段《数据结构和算法》课程的内容和王争老师在即刻时间上的《数据结构和算法之美》系列课程(墙裂推荐)进行了一些排版参考和笔记性梳理。这些文章作为笔记总结,一方便是为了夯实自己的基础,一方面为同事和朋友提供一些日后相关内容解释的参考和公开的分享链接。同时数据结构相关内容也必须要具备某一种编程语言的基础知识且内容较为庞杂枯燥。如果是未曾接触过编程语言的读者,建议请先选择一门编程语言,并了解其基础语法,这样才能在学习数据结构与算法的过程中坚持下去。这里我的笔记使用的编程语言为 Python3 ,且大部分图片为手绘。

数据结构和算法解决计算机的什么问题

数据结构和算法自身解决的是“快”和“省”的问题,即如何让编写的程序能够更快得在海量且无序的数据里面找到答案;同时如何让程序在运行的过程中更好的节省计算机存储空间(主要指计算机内存),以防止干扰物理机(服务器或者个人电脑等)其它软件程序的运行。这里我们假设计算机CPU是一个疯狂的剁手党,我们把要处理的数据想象成物品放入包裹(从内存写入硬盘)里或者收到后开始拆开包裹,取出物品(从硬盘读入内存)。计算机架构里,通常我们只有把数据装载到内存,我们才能一窥数据的全貌,并处理它,而硬盘仅仅是堆放整理好了的数据包裹的地方,这就是内存和硬盘的区别。我们获取将面对两种方式:

1)将很多东西一起集中放在一个包裹里面;

2)将每一个物品打上标签放在自己独属的包裹里。

那么在这里我们就会在装包裹和拆包裹面对不同的问题和便利。

1)装包裹的方式(内存写入硬盘)无疑是第二个时间长,这就解释了为什么在计算机中,拥有许多零散文件的压缩包解压过程总是比差不多大小的几个大文件组成的压缩包慢;

2)如果剁手党收到包裹后,扛着大包裹上楼(相当于将海量数据一次性装载到内存)无疑是很吃力的。这时候如果只是想拿到自己最中意的手机包裹,肯定是打了标签的小包裹更方便(相当于海量数据被分割成很多小块,并已经打上标签存储到硬盘上,就能快速找到手机标签的数据导入内存)。

总而言之,数据结构和算法解决的是面对海量且杂乱数据的时候,如何更省和更快整理和查找数据的问题。

什么是复杂度分析

复杂度分析要求首先我们要有一个具体问题,比如剁手党如何在购买的一堆东西中找到心爱手机。从时间角度来讲,剁手党肯定是针对性的找单号为手机的包裹最快,而不是把零食、牛奶和手机等等一起混乱的放在一个包裹里翻找;从空间角度讲,剁手党扛着几十斤的包裹上楼和拿着几百克的手机上楼孰轻孰重也高下立判。这就催生了时间复杂度和空间复杂度分析。

为什么要时间和空间复杂度分析

大部分原因已经由前文讲述,但还有一个原因。我们这里所说的时间复杂度和空间复杂度分析是一种事前统计法。我们不可能跟测评一样,把找包裹和拆包裹的不同过程都掐个秒表实践一下,并算一下时间(事后统计法),再去抉择。

大 O 分析法

时间复杂度分析

数据结构和算法基本上侧重于时间复杂度分析,即代码执行时间的分析。由于代码运行时间的复杂度相比于代码运行占用内存复杂度的情况要多得多,所以传统意义上的数据结构与算法都是对运行时间的分析,也可理解为预估代码的执行效率。如下代码所示,我们可以分析一下sum_demo函数的执行时间,假设每一行代码为 1 ms ,代码的意思为默认从 1 至 10000 的累加,运行求和结果为:50005000 。每一行的执行时间为 1 + 2 ∗ 10000 + 1 1+2*10000+1 1+210000+1 ms ,由于 capacity (默认10000)是个变量,可以当成变量 n ,我们可以得出代码总运行时间为: T ( n ) = 2 + 2 ∗ n T(n)=2+2*n T(n)=2+2n

class Complexity:def __init__(self, capacity: int = 10000):self._capacity = capacitydef sum_demo(self) -> int:summary = 0for index in range(1, self._capacity + 1, 1):summary += indexreturn summaryif __name__ == "__main__":print("sum demo result: %d" % Complexity().sum_demo())

这里我们会发现详细的计算公式并不利于我们快速估算,同时我们也不需要具体的执行时间,只需要一个能直观表现运行时间变化趋势的公式。根据数学中对变化趋势的定义,我们可以将常数、系数和公式中所有低阶项全部舍弃,便产生了大 O 表示法,即 T ( n ) = O ( 2 + 2 ∗ n ) = O ( n ) T(n)=O(2+2*n)=O(n) T(n)=O(2+2n)=O(n)。这种分析法在时间领域,我们也可以叫做渐进时间复杂度。

    def sum_demo_2(self) -> int:summary = 0for index1 in range(1, self._capacity + 1, 1):summary += index1for index2 in range(1, self._capacity + 1, 1):for index3 in range(1, self._capacity + 1, 1):summary = summary + index2 + index3return summary

上面的代码进行复杂度分析为 T ( n ) = O ( 1 + 2 ∗ n + n ∗ 2 n + 1 ) = O ( 2 n 2 + 2 n + 2 ) T(n)=O(1+2*n+n*2n+1)=O(2n^2+2n+2) T(n)=O(1+2n+n2n+1)=O(2n2+2n+2),根据刚刚说的取最高阶项,并且舍弃常数和系数规律,即 T ( n ) = O ( n 2 ) T(n)=O(n^2) T(n)=O(n2)

常见的时间复杂度

O ( 1 ) O(1) O(1)

这个代表前文代码 summary = 0最简单的一行代码的时间估算,即运行时间为 1 ms

O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2)

这个之前已经用代码展示过了,不在赘述。

O ( l o g n ) 和 O ( n l o g n ) O(logn) 和 O(nlogn) O(logn)O(nlogn)
    def log_n(self) -> int:index = 1while index <= self._capacity:index = 3 * indexreturn indexdef n_log_n(self) -> int:summary = 0for _ in range(1, self._capacity + 1, 1):index = 1while index <= self._capacity:index = 3 * indexsummary += indexreturn summary

我们先观察log_n函数,这里while循环的判断条件相当于 3 x < = 10000 3^x<=10000 3x<=10000,而 x 我们就可以看成循环的次数,所以我们就可以求出 x = l o g 3 10000 x=log_{3}^{10000} x=log310000,这里数据结构规定,对数函数不论下标是什么,都舍弃。我们便可得出: T ( n ) = O ( l o g n ) T(n)=O(logn) T(n)=O(logn) ;那么我们不难看出函数n_log_n的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn) 。我们从代码运行结果也可以发现两个函数执行时间(index变量返回结果估算)结果大约相差一万倍。

时间复杂度加法法则和乘法法则

上面的代码我们都使用了self._capacity一个变量作为参数,所以我们可以直接取高阶项为变化趋势,其它低阶项直接舍弃。但是我们面对多个不同变量的时候,我们不能错误的把不同变量变化趋势简单取为最高阶项,这就出现了加法法则和乘法法则:

    def m_add_n(self, value1: int, value2: int) -> int:summary = 0for index in range(1, value1 + 1, 1):summary += indexfor index in range(1, value2 + 1, 1):summary += indexreturn summarydef m_times_n(self, value1: int, value2: int) -> int:summary = 0for _ in range(1, value1 + 1, 1):for index in range(1, value2 + 1, 1):summary += indexreturn summary

由于value1value2是两个不同的变量,那么可以看出两者的时间复杂度分别写为 O ( m + n ) O(m+n) O(m+n) O ( m n ) O(mn) O(mn)

空间复杂度分析

空间复杂度比较简单,虽然我们的变量 self._capacity 在对象初始化的时候只会调用一次,空间复杂度为 O ( 1 ) O(1) O(1) ,但基于此每执行一次for循环会申明 10000 * 单个 int 型所占的字节。空间复杂度同样适用取最高阶项,舍弃常数和系数的规律,所以如下代码的空间复杂度分别为 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) 。我们发现这里sum_demo_2的空间复杂度会像时间复杂度随着数据量增加飞速增长。更糟糕的是,这里虽然有 Python 垃圾自动回收机制,但对象使用之后需要等待一段时间才会被回收销毁取释放内存,所以 O ( n 2 ) O(n^2) O(n2) 时间和空间复杂度造成的时空浪费在海量数据面前非常致命。

    def sum_demo_1(self) -> int:summary = 0for index in range(1, self._capacity + 1, 1):summary += indexreturn summarydef sum_demo_2(self) -> int:summary = 0for index1 in range(1, self._capacity + 1, 1):summary += index1for index2 in range(1, self._capacity + 1, 1):for index3 in range(1, self._capacity + 1, 1):summary = summary + index2 + index3return summary

复杂度曲线

通常我们认为:基于海量的数据,代码效率为 O ( l o g n ) < O ( n ) < O ( n l o g n ) < O ( n 2 ) O(logn)<O(n)<O(nlogn)<O(n^{2}) O(logn)<O(n)<O(nlogn)<O(n2) , 如图所示:

在这里插入图片描述

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

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

相关文章

INT303 Big Data 个人笔记

又来到了经典半个月写一个学期内容的环节 目前更新至Lec{14}/Lec14 依旧是不涉及代码&#xff0c;代码请看学校的jupyter notebook~ Lec1 Introduction 介绍课程 TopicRangeTopic 1: Introduction to Big Data AnalyticsLec1~Lec3Topic2: Big data collection and visualiza…

日撸 Java 三百行(21 天: 二叉树及其基本操作)

注意&#xff1a;这里是JAVA自学与了解的同步笔记与记录&#xff0c;如有问题欢迎指正说明 目录 前言 一、一对多的结构&#xff1a;树形结构 二、二叉树 1.二叉树的体现运用 2.二叉树存储 三、二叉树遍历 1.树遍历的递归思想中的“三角抉择” 2.树的前、中、后序遍历…

C语言每日一练 —— 第21天:算法的应用

文章目录 前言一、算法简介1、推荐算法2、最短路算法3、最值算法4、排序算法5、压缩算法6、加密算法 二、为什么要学算法1、面试时2、工作中 三、算法能给我们带来什么能力的提升1、抽象问题的能力2、解决问题的能力3、编写代码的能力4、调试能力1&#xff09;画图2&#xff09…

C语言基础学习

**1.2 C语言程序设计入门三步骤 程序设计入门三步骤&#xff1a; &#xff08;1&#xff09;安装软件并开发HelloWorld程序。 &#xff08;2&#xff09;掌握基本的输入输出方法。 &#xff08;3&#xff09;理解该语言中程序的基本结构。 1.2.1 安装软件并开发第一个HelloWo…

BP算法Java实现

我们上次已经把公式给推导了出来。还举了例子&#xff0c;不懂的理论的点击这里&#xff0c;老师的代码   这回我们将要用Java进行初步实现&#xff0c;这个代码是我参考老师的&#xff0c;里面附带了详细的注解。要成功运行需要一些包&#xff0c;需要的可以联系我。 public…

关系代数和SQL语法

数据分析的语言接口 OLAP计算引擎是一架机器&#xff0c;而操作这架机器的是编程语言。使用者通过特定语言告诉计算引擎&#xff0c;需要读取哪些数据、以及需要进行什么样的计算。编程语言有很多种&#xff0c;任何人都可以设计出一门编程语言&#xff0c;然后设计对应的编译…

优雅的对象

最近一口气读完了二百多页的《Elegant Objects》。可能因为整理自博客所以排版一般,而且才二百多页定价却40多刀。但读过之后发现超值,甚至还想去买第二卷。作者观点大多比较激进,对自己的理念异常坚定,所以经常使用诸如“绝对不要使用XXX”、“记住XXX,就这样,句号”。但…

深入理解Java 8 Lambda

关于 深入理解 Java 8 Lambda&#xff08;语言篇——lambda&#xff0c;方法引用&#xff0c;目标类型和默认方法&#xff09;深入理解 Java 8 Lambda&#xff08;类库篇——Streams API&#xff0c;Collector 和并行&#xff09;深入理解 Java 8 Lambda&#xff08;原理篇——…

自然语言处理中注意力机制综述

https://www.toutiao.com/a6655120292144218637/ 目录 1.写在前面 2.Seq2Seq 模型 3.NLP中注意力机制起源 4.NLP中的注意力机制 5.Hierarchical Attention 6.Self-Attention 7.Memory-based Attention 8.Soft/Hard Attention 9.Global/Local Attention 10.评价指标 11.写在后面…

【深度学习基础】从零开始的炼丹生活00——机器学习数学基础以及数值计算数值优化方法

正值假期&#xff0c;决定恶补机器学习、深度学习及相关领域&#xff08;顺便开个博客&#xff09;。首先学习一下数学基础以及数值计算的方法&#xff08;主要参考《深度学习》&#xff09; 一、数学基础 这里简单复习一下机器学习相关的数学1.线性代数 范数 衡量一个向量的…

“泰迪杯”挑战赛 -利用非侵入式负荷检测进行高效率数据挖掘(完整数学模型)

目录 1 研究背景与意义 2 变量说明 3 问题分析 4 问题一 4.1 数据预处理 4.1.1 降噪处理 4.1.2 数据变换 4.2 负荷特征分析 4.2.1 暂态特征 4.2.2 稳态特征 5 问题二 5.1 相似度与权系数 5.2 模型建立 5.3 模型求解 6 问题三 6.1 事件检测算法 6.2 模型建立 6.3 模型求解…

37%原则如何优化我们做决定的时间

当需要百(千&#xff0c;万…)里挑一时&#xff0c;需要权衡最优解和效率&#xff0c;有一个37%原则比较有趣。 整个择优过程分为两个阶段&#xff1a; 观望&#xff1a;在前面 k k k个候选者中冒泡记录最优者 p p p&#xff0c;其分数为 V p V_p Vp​&#xff0c;但并不选择…

清风数学建模学习笔记——层次分析法

目录 一、模型简介 二、建模步骤 三、模型总结 一、层次分析法——模型简介 层次分析法&#xff0c;简称AHP&#xff0c;是指将与决策总是有关的元素分解成目标、准则、方案等层次&#xff0c;在此基础之上进行定性和定量分析的决策方法。该方法是美国运筹学家匹茨堡大学教授萨…

Attention is all you need ---Transformer

大语言模型已经在很多领域大显身手&#xff0c;其应用包括只能写作、音乐创作、知识问答、聊天、客服、广告文案、论文、新闻、小说创作、润色、会议/文章摘要等等领域。在商业上模型即产品、服务即产品、插件即产品&#xff0c;任何形态的用户可触及的都可以是产品&#xff0c…

you-get下载速度慢解决方法

Python版本&#xff1a;3.10 运行环境&#xff1a;Windows10 问题描述&#xff1a;在使用you-get下载X站视频时网速很慢&#xff0c;并一直限制在某个值,通过以下办法即可恢复正常网速 解决办法&#xff1a; 进入windows 安全中心-病毒和威胁防护-管理设置点击添加或删除排…

Microsoft store下载速度过慢

最开始是进入Microsoft store点击安装后一直无响应&#xff0c;后来知道这是因为Microsoft store下载速度过慢。下边几个步骤都尝试了&#xff0c;个人认为最重要的是Windows Update设置步骤&#xff0c;刚开始可能一直没有正确打开 修改DNS 右键任务栏网络图标->打开“网…

Linux网络编程 socket编程篇(一) socket编程基础

目录 一、预备知识 1.IP地址 2.端口号 3.网络通信 4.TCP协议简介 5.UDP协议简介 6.网络字节序 二、socket 1.什么是socket(套接字)&#xff1f; 2.为什么要有套接字&#xff1f; 3.套接字的主要类型 拓】网络套接字 三、socket API 1.socket API是什么&#xff1f; 2.为什么…

如何预防ssl中间人攻击?

当我们连上公共WiFi打开网页或邮箱时&#xff0c;殊不知此时可能有人正在监视着我们的各种网络活动。打开账户网页那一瞬间&#xff0c;不法分子可能已经盗取了我们的银行凭证、家庭住址、电子邮件和联系人信息&#xff0c;而这一切我们却毫不知情。这是一种网络上常见的“中间…

[保研/考研机试] KY3 约数的个数 清华大学复试上机题 C++实现

题目链接&#xff1a; KY3 约数的个数 https://www.nowcoder.com/share/jump/437195121691716950188 描述 输入n个整数,依次输出每个数的约数的个数 输入描述&#xff1a; 输入的第一行为N&#xff0c;即数组的个数(N<1000) 接下来的1行包括N个整数&#xff0c;其中每个…

wsl2安装mysql环境

安装完mysql后通过如下命令启动mysql service mysql start 会显示如下错误&#xff1a; mysql: unrecognized service 实际上上面显示的错误是由于mysql没有启动成功造成的 我们要想办法成功启动mysql才可以 1.通过如下操作就可以跳过密码直接进入mysql环境 2.如果想找到my…