【数据结构】复杂度的重要性—–决定程序运行的效率

【数据结构】复杂度的重要性—–决定程序运行的效率

前言

在我们写算法的时候,常常会需要考虑一个问题:这个算法好不好?而这个“好”实际上就取决于是算法的复杂度。

在这里插入图片描述

算法复杂度Algorithmic Complexity)是指算法在编写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。应用于数学和计算机导论。

我们知道,同一个问题可以使用不同的算法来解决,而这里的不同一般来说也是可以从复杂度来看出的,当然,也不排除有相同复杂度但不同写法的算法,这里只作参考。

一个算法的好坏影响到了很多实际性的问题,在程序中效率是极其重要的,一个算法的评价主要从时间复杂度和空间复杂度来考虑。

在介绍这两个复杂度之前,我们需要了解一个概念:复杂度并不是具体的数值或者是大小表示,它实际上是一个量级的概念

比如O(n)和O(n+1)。很明显,它们是同一个量级,只差了1,那么它们实际上可以写成同一个,也就是O(n),甚至像O(2n),它和上面两者也是同一个量级;但是,像O(n)和O(n^2),这俩实际上并不属于同一个量级。它们之间隔了一个次方,那么就有可能存在大小的很大差距,所以这两个复杂度是两个不同的个体。

接下来对这两个复杂度进行具体介绍。

时间复杂度

基本定义和理解

时间复杂度衡量的是算法运行时间随输入规模的增长情况。

对于算法的运行时间,在实际中,由于每台计算机的硬件和软件环境的不同,往往不能精确计算执行所需时间。所以我们在讨论时间复杂度的时候,仅仅从理论角度,也就是视作计算机的环境不变,来进行讨论。

影响算法时间代价的具体有两个方面:问题规模语句频度

A.问题规模是算法求解问题输入量的多少,是问题大小的本质表示,一般用整数n表示。

B.语句频度是一条语句的重复执行次数。一般来说,这个次数会用一个函数来表示,而这个函数代表着算法执行时间的增长率算法执行时间的增长率称作渐进时间复杂度,也就简称为时间复杂度

时间复杂度通常使用O(n)来表示,算法的复杂度存在最好、最坏等情况,那么在这里我们取算法的最坏运行情况作为O(n)

在我们进行时间复杂度的解答时,实际上不需要这么复杂的解释。我们可以将其总结为一句话:

只分析算法中最耗时的操作。

由于我们考虑的是算法的最坏运行情况,并且是以量级来计算,那么我们实际上只需要分析算法中最耗时的操作即可。

分析步骤

1.确定输入规模 (n):输入规模通常是算法中主要变量的数量,例如数组的长度。

2.识别基本操作:确定算法中最耗时的操作,其他比较繁琐、或者特殊的语句忽视。

3.分析每部分的操作次数:计算基本操作在不同结构中的次数,例如循环、递归。

4.累加所有部分的操作次数:将各部分的操作次数加起来,得到总操作次数。

5.用大O符号表示:忽略常数和低阶项,提取时间复杂度的主要部分。这里的目的实际上就是统一量级。

使用这样的步骤,我们就可以较好地解决时间复杂度的分析了。

举例

示例1:简单循环

def sum_array(arr):total = 0for i in range(len(arr)):total += arr[i]return total

步骤1:确定输入规模

输入是数组 arr,其长度为 n

步骤2:识别基本操作

基本操作是加法 total += arr[i]

步骤3:分析每部分的操作次数

  • total = 0:1 次
  • for i in range(len(arr)):循环执行 n
  • total += arr[i]:循环体内执行 n

步骤4:累加所有部分的操作次数

总操作次数为 1+n+n=1+2n1 + n + n = 1 + 2n1+n+n=1+2n。

步骤5:用大O符号表示

忽略常数项和系数,时间复杂度为 O(n)。

示例2:嵌套循环

def bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]

步骤1:确定输入规模

输入是数组 arr,其长度为 n

步骤2:识别基本操作

基本操作是比较和交换 if arr[j] > arr[j+1]arr[j], arr[j+1] = arr[j+1], arr[j]

步骤3:分析每部分的操作次数

步骤4:累加所有部分的操作次数

分析这里的操作次数,我们可以使用更为简单的方法,请注意,这里的for循环中还嵌套了一个for循环,那么我们可以理解为:在进行大循环的时候,也会进行一次小循环,而小循环中的语句会进行n次,那么就是O(n);而大循环会进行n次小循环,那么总的时间复杂度就是O(n*n)也就是O(n^2)。

注意:遇见嵌套类的题目,我们都这样计算:嵌套中有几个循环,就是n的几次方。

步骤5:用大O符号表示

忽略常数项和系数,时间复杂度为 O(n^2)。

示例3:二分查找

def binary_search(arr, target):left, right = 0, len(arr) - 1while left <= right:mid = (left + right) // 2if arr[mid] == target:return midelse if arr[mid] < target:left = mid + 1else:right = mid - 1return -1

步骤1:确定输入规模

输入是数组 arr,其长度为 n

步骤2:识别基本操作

基本操作是比较 arr[mid] == target

步骤3:分析每部分的操作次数

  • left, right = 0, len(arr) - 1:1 次
  • while left <= right:循环次数由 leftright 的变化决定,每次循环减半,最多执行log2(n)次。

步骤4:累加所有部分的操作次数

总操作次数为 1+log2(n)

步骤5:用大O符号表示

忽略常数项和低阶项,时间复杂度为 O(log n)。

经过以上的介绍和举例,相信各位已经能够游刃有余地解决时间复杂度的问题了。

空间复杂度

基本定义和理解

与时间复杂度类似,空间复杂度是指算法在计算机内执行时所需存储空间的度量。当我们需要区别算法时,我们应该看到的是每个算法的不同处,由于输入的初始数据所占的存储空间是已经确定的,那么在计算空间复杂度时,我们往往只分析执行过程中所需要额外的存储空间大小。

分析步骤

1.确定输入规模 (n):输入规模通常是算法中主要变量的数量,例如数组的长度。

2.识别存储需求:确定算法中每个变量和数据结构所需的存储空间。

3.分析每部分的存储空间需求:计算不同部分占用的空间,如局部变量、数组、递归调用栈等。

4.累加所有部分的存储空间需求:将各部分的存储空间加起来,得到总的空间需求。

5.用大O符号表示:忽略常数和低阶项,提取空间复杂度的主要部分。

举例

示例1:简单循环

def sum_array(arr):total = 0for i in range(len(arr)):total += arr[i]return total

步骤1:确定输入规模

输入是数组 arr,其长度为 n

步骤2:识别存储需求

  • arr:长度为 n,空间需求为 O(n)
  • total:一个整数,空间需求为 O(1)
  • i:一个整数,空间需求为 O(1)

步骤3:分析每部分的存储空间需求

  • arr:O(n)
  • total:O(1)
  • i:O(1)

步骤4:累加所有部分的存储空间需求

总空间需求为 O(n)+O(1)+O(1)=O(n)。

步骤5:用大O符号表示

忽略常数项和低阶项,空间复杂度为 O(n)。

示例2:递归函数

def factorial(n):if n == 0:return 1else:return n * factorial(n-1)

步骤1:确定输入规模

输入是整数 n

步骤2:识别存储需求

  • 递归调用栈:每次递归调用会占用栈空间。

步骤3:分析每部分的存储空间需求

  • 每次递归调用占用 O(1) 空间,最多递归调用 n 次。

步骤4:累加所有部分的存储空间需求

总空间需求为 O(1)∗n=O(n)。

步骤5:用大O符号表示

忽略常数项和低阶项,空间复杂度为 O(n)。

示例3:使用辅助数组

def merge_sort(arr):if len(arr) > 1:mid = len(arr) // 2L = arr[:mid]R = arr[mid:]merge_sort(L)merge_sort(R)i = j = k = 0while i < len(L) and j < len(R):if L[i] < R[j]:arr[k] = L[i]i += 1else:arr[k] = R[j]j += 1k += 1while i < len(L):arr[k] = L[i]i += 1k += 1while j < len(R):arr[k] = R[j]j += 1k += 1

步骤1:确定输入规模

输入是数组 arr,其长度为 n

步骤2:识别存储需求

  • arr:长度为 n,空间需求为 O(n)
  • 辅助数组 LR:总长度为 n,空间需求为 O(n)

步骤3:分析每部分的存储空间需求

  • arr:O(n)
  • 辅助数组 LR:O(n)
  • 局部变量 i, j, k, mid:O(1)

步骤4:累加所有部分的存储空间需求

总空间需求为 O(n)+O(n)+O(1)=2O(n)+O(1)=O(n)。

步骤5:用大O符号表示

忽略常数项和低阶项,空间复杂度为 O(n)。

注意:在空间复杂度的计算中,大部分都是O(n)和O(1),这两个复杂度是最为常见的。

如何理解和应用复杂度分析

理解复杂度分析的核心是**能够评估算法在最坏、最好和平均情况下的性能。**这有助于我们在开发过程中选择最合适的算法和数据结构以确保程序的高效运行。

算法的高效性往往在算法指标中占据较高位置,所以只要我们使得复杂度越,高效性越,那么算法也就会越

的存储空间需求**

总空间需求为 O(n)+O(n)+O(1)=2O(n)+O(1)=O(n)。

步骤5:用大O符号表示

忽略常数项和低阶项,空间复杂度为 O(n)。

注意:在空间复杂度的计算中,大部分都是O(n)和O(1),这两个复杂度是最为常见的。

如何理解和应用复杂度分析

理解复杂度分析的核心是**能够评估算法在最坏、最好和平均情况下的性能。**这有助于我们在开发过程中选择最合适的算法和数据结构以确保程序的高效运行。

算法的高效性往往在算法指标中占据较高位置,所以只要我们使得复杂度越,高效性越,那么算法也就会越

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

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

相关文章

如何在电脑上安装两个flutter版本

Flutter Version Manager (FVM): Flutter的版本管理终极指南 Mac的flutter多版本管理之fvm的安装及使用 一、安装fvm brew tap leoafarias/fvm brew install fvm这个错误可能是由于网络问题或者 Git 配置问题导致的&#xff0c;我开启了梯子就可以了 brew install watchman…

Low Memory Killer in Android

目录 低内存管理&#xff08;Linux vs Android&#xff09; Linux内存回收 shrink_slab原理 shrink_zone原理 oom killer oom killer设计原则 OOM killer具体实现 android的lmk(Low Memory Killer) Android系统特点 oom killer在android中的不足 ​​​​​​​LMK概…

基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用

背景 随着互联网服务的广泛普及与技术应用的深入发展&#xff0c;日志数据作为记录系统活动、用户行为和业务操作的宝贵资源&#xff0c;其价值愈发凸显。然而&#xff0c;当前海量日志数据的产生速度已经远远超出了传统数据分析工具的处理能力&#xff0c;这不仅要求我们具备…

【机器学习】机器学习与AI大数据的融合:开启智能新时代

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 机器学习与AI大数据的融合 &#x1f4d2;1. 引言&#x1f4d5;2. 机器学习与大数据&#x1f3a9;机器学习与大数据的特征&#x1f388;大数据如…

驱动开发之platform总线

1.前言 在前面的实验以及提出的各种问题中&#xff0c;为了提高移植性&#xff0c;降低模块耦合度&#xff0c;提让模块高内聚&#xff0c;分离device与driver是一个必然的趋势了。为了解决这个问题&#xff0c;心心念念的platform总线出来。 linux从2.6起就加入了一套新的驱…

python中利用cartopy库绘制SST图像

1. Cartopy简介 Cartopy 是一个开源的 Python 库&#xff0c;用于绘制地图和地理数据分析。它结合了 matplotlib 的绘图功能和 shapely、pyproj 等库的地理空间数据处理能力&#xff0c;为用户提供了在地图上可视化数据的强大工具。 以下是 Cartopy 的一些主要特点和功能&#…

探索不同类型的“低”之魅力

随着数字化转型的浪潮不断高涨&#xff0c;低代码平台&#xff08;LCDP&#xff09;已逐渐成为企业快速构建和迭代应用程序的重要工具。低代码平台以其高效、灵活和易于集成的特点&#xff0c;受到越来越多企业的青睐。然而&#xff0c;低代码平台并非一蹴而就的单一产品&#…

CST电磁仿真软件表面等离子极化激元SPP --- 一维光栅耦合 - 衍射模式, 效率, Floquet端口

这两期我们看一下衍射光栅的高阶衍射、衍射效率、反射率。具体到仿真设置&#xff0c;就是Floquet端口的模式分析&#xff0c;S参数与衍射效率和反射率的关系。那么研究这些衍射和表面等离子极化激元SPP有什么关系呢&#xff1f;关系可大了&#xff0c;光栅是一种能够用来激励出…

告别鼠标,安卓模拟鼠标,绘图板,手写板操作电脑PC端,卡卡罗特也说好,儿童节快乐

家人们&#xff0c;上链接了&#xff1a;https://download.csdn.net/download/jasonhongcn/89387887 横屏模式&#xff1a; 竖屏模式&#xff1a; 操作说明&#xff1a; 1. 手势滑动模拟鼠标移动 2. 界面如果有滚动条&#xff0c;右手指按紧&#xff0c;通过左手指移动实现…

力扣:101. 对称二叉树

101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&#xff1a; …

mysql DDL——增删改

简略版&#xff1a; 文字化&#xff1a; 1.对全部字段添加数据&#xff1a;insert into 表名 values (值1&#xff0c;值2&#xff0c;值3...); 2.对指定字段添加数据&#xff1a;insert into 表名 (字段名1&#xff0c;字段名2...) values &#xff08;值1&#xff0c;值2..…

跨区域文件管控过程中 如何保障安全和效率?

跨区域文件管控是指在跨越不同地域或区域的情况下对文件进行管理和控制的过程。这种控制可能涉及多个方面&#xff0c;包括安全性、合规性和管理效率等。 为了有效进行跨区域文件管控&#xff0c;组织通常需要采取一系列策略和措施&#xff0c;例如&#xff1a; 1、加密和安全…

旺店通·企业奇门和金蝶云星空接口打通对接实战多系统间数据

旺店通企业奇门和金蝶云星空接口打通对接实战 来源系统:旺店通企业奇门 慧策&#xff08;原旺店通&#xff09;是一家技术驱动型智能零售服务商&#xff0c;基于云计算PaaS、SaaS模式&#xff0c;以一体化智能零售解决方案&#xff0c;帮助零售企业数字化智能化升级&#xff0c…

二进制文件(.bin等文件)转C语言数组形式hex文件(.c等文件)

使用python脚本把二进制文件&#xff08;.bin等文件&#xff09;转C语言数组形式hex文件&#xff08;.c等文件&#xff09;&#xff0c;具体代码如下&#xff1a; &#xff08;1&#xff09;读取.bin文件数据 &#xff08;2&#xff09;生成C语言数组定义 &#xff08;3&…

深圳雷龙LSYT201B语音控制模组

文章目录 前言一、芯片简介处理器外设音频蓝牙电源封装温度 二、功能简介管脚描述 三、应用场景四、使用说明五、硬件连接六、FAQ总结 前言 今天拿到的语音控制板是LSYT201B模组&#xff0c;它是深圳市雷龙发展有限公司基于YT2228芯片开发的一款面向智能家居控制的离线语音控制…

员工转正申请精选12个模板供参考

随着社会在不断地进步&#xff0c;我们会经常使用各种各样的申请书&#xff0c;转正申请书就是申请书的一种&#xff0c;那么转正申请书是怎么写的呢&#xff1f;下面是我收集整理的员工转正申请书几个版本&#xff0c;仅供参考&#xff0c;希望能够帮助到大家。别忘了一键三连…

贵的SSL证书跟便宜的SSL证书有什么不一样的?

目前SSL证书市场上从几十块钱的到上万元的都是有的&#xff0c;那么这些着证书之间有什么不同&#xff1f;怎么收费差这么多&#xff1f; 一&#xff1a;从证书的认证安全等级来说 比较便宜的SSL证书一般都是DV验证级别的。也就是说只验证域名的所有权&#xff0c;做一个DNS解…

03.0docker安装

docker简介 docker的主要目标是"Build,Ship and Run any App,Angwhere",构建&#xff0c;运输&#xff0c;处处运行 部署服务&#xff0c;环境问题 一次构建&#xff0c;处处运行 docker是一种软件的打包技术 构建&#xff1a;做一个docker镜像 运输&#xff1a;do…

数据分析常用模型合集(一)AARRR模型和漏斗模型

准备把常用的数据分析模型&#xff0c;像什么AARRR&#xff0c;RFM之类的&#xff0c;逐个全部写一下&#xff1b; 最好能带点案例和代码&#xff0c;搞一个小合集。 最终达到完全不懂的人&#xff0c;看完就能知道得差不多&#xff1b; 数据分析常用模型合集&#xff08;二…

大型语言模型简介

大型语言模型简介 大型语言模型 (LLM) 是一种深度学习算法&#xff0c;可以使用非常大的数据集识别、总结、翻译、预测和生成内容。 文章目录 大型语言模型简介什么是大型语言模型&#xff1f;为什么大型语言模型很重要&#xff1f;什么是大型语言模型示例&#xff1f;大型语…