【算法基础】时间复杂度和空间复杂度

目录

1 算法的评价

2 算法复杂度

2.1 时间复杂度(Time Complexity)

2.1.1 如何计算时间复杂度:

2.1.2 常见的时间复杂度类别与示例

2.2 空间复杂度

2.2.1 如何计算空间复杂度

2.2.2 常见的空间复杂度与示例

3 时间复杂度和空间复杂度计算示例

例子1:计算数组中所有元素的和。

例子2:快速排序算法。

例子3:递归实现斐波那契数列。

例子4:非递归实现的斐波那契数列。

例子5:二分查找算法。

例子6:冒泡排序算法。


1 算法的评价

        评价算法的性能和效果是计算机科学和数据科学中的关键任务之一。如何评价算法的优劣可以从以下几方面展开:

        时间复杂度和空间复杂度是算法性能分析的关键指标,它们用于衡量算法在处理不同规模输入时的时间和空间资源消耗。

2 算法复杂度

2.1 时间复杂度(Time Complexity)

        时间复杂度是指在算法执行过程中,所需的时间资源与问题规模之间的关系。它主要衡量的是算法的执行效率,用于评估算法在不同规模数据下的操作时间。

        时间复杂度通常使用大O符号表示,表示算法运行时间的增长率。

         需要注意的是,时间复杂度只考虑算法的主要操作数量级,忽略了常数因子和低阶项。因此,两个时间复杂度相同的算法在实际执行中可能有着不同的执行效率。

2.1.1 如何计算时间复杂度:

  • 分析每个操作的时间复杂度,包括循环、条件语句和函数调用。
  • 计算每个操作的执行次数,通常是输入规模的函数。
  • 合并所有操作的复杂度,通常选择最大的那个作为算法的时间复杂度。 

时间复杂度的计算涉及以下几个方面:

  1. 基本操作次数: 时间复杂度的计算通常关注算法中执行的基本操作次数,例如赋值操作、比较操作、算术运算等。通常将这些操作的数量与输入规模相关联。

  2. 循环结构: 如果算法包含循环结构(例如for循环、while循环),需要考虑循环的迭代次数以及每次迭代中的基本操作数量。

  3. 递归调用: 对于递归算法,需要考虑递归的深度以及每次递归调用的时间复杂度。通常使用递归方程(递归关系式)来表示递归算法的时间复杂度。

  4. 分支结构: 如果算法包含分支结构(例如if语句),需要考虑每个分支的执行次数以及分支中的基本操作数量。

  5. 输入规模: 时间复杂度的计算通常与输入规模有关。输入规模表示算法操作的数据量或问题的大小,通常用符号n表示。

2.1.2 常见的时间复杂度类别与示例

  1. 常数时间复杂度(O(1)):无论问题规模多大,算法的执行时间都保持不变。例如,直接访问数组中的一个元素。

  2. 线性时间复杂度(O(n)):随着问题规模的增大,算法的执行时间也按线性比例增长。例如,遍历一个数组或链表中的所有元素。

  3. 对数时间复杂度(O(logn)):算法执行时间随着问题规模的增大而增长,但不是线性关系,而是以对数速率增长。例如,二分查找算法。

  4. 平方时间复杂度(O(n^2)):算法的执行时间与问题规模的平方成正比。例如,双重循环嵌套的算法。

  5. 指数时间复杂度(O(2^n)):算法的执行时间呈指数级增长,非常低效。例如,穷举法解决NP完全问题。    

O(1) - 常数时间复杂度: 算法的执行时间是固定的,与输入规模无关。示例:

def constant_time_algorithm(arr):return arr[0]

O(log n) - 对数时间复杂度: 算法的执行时间随着输入规模的增加以对数方式增加。示例:

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

O(n) - 线性时间复杂度: 算法的执行时间与输入规模成正比。示例

def linear_search(arr, target):for i in range(len(arr)):if arr[i] == target:return ireturn -1

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]

2.2 空间复杂度(Space Complexity)

        空间复杂度是指算法在执行过程中所需的额外内存空间,它与问题规模之间的关系。空间复杂度用于评估算法的内存占用情况和资源消耗。

        通常使用大O符号表示空间复杂度,表示算法所需的额外内存空间与问题规模之间的增长关系。

2.2.1 如何计算空间复杂度

  • 分析算法的每个数据结构、变量和递归调用,以确定它们的空间占用。
  • 计算每个数据结构和变量的空间占用,通常是常数项和与输入规模相关的项的和。
  • 合并所有空间占用,通常选择最大的那个作为算法的空间复杂度。

空间复杂度的计算包括以下几个方面:

  1. 固定内存消耗: 指算法在运行过程中需要固定数量的内存空间,与输入规模无关。常见的固定内存消耗包括函数参数、常量变量、全局变量等。

  2. 额外数据结构: 如果算法使用了额外的数据结构来存储信息,如数组、列表、树、堆栈、队列等,需要考虑这些数据结构所占用的内存空间。通常需要考虑数据结构的大小和数量。

  3. 递归调用: 递归算法会使用栈空间来存储每一次递归调用的状态。递归的深度和每次递归调用的内存消耗会影响空间复杂度。

  4. 临时变量: 算法中使用的临时变量和计算过程中的中间结果也会占用内存空间。需要考虑这些变量的数量和大小。

  5. 输入数据的存储: 输入数据的存储也需要考虑在内。如果算法需要将整个输入数据存储在内存中,则空间复杂度与输入数据的大小成正比。

2.2.2 常见的空间复杂度与示例

  1. 常数空间复杂度(O(1)):算法所需的额外内存空间是一个常量值,不随问题规模的增大而改变。例如,只使用固定数量的变量或常量大小的数组。

  2. 线性空间复杂度(O(n)):算法所需的额外内存空间随问题规模的增大而线性增长。例如,需要根据输入构建一个同等大小的新数据结构。

  3. 平方空间复杂度(O(n^2)):算法所需的额外内存空间随问题规模的增大而平方级增长。例如,需要构建一个二维数组来存储所有可能的组合。

  4. 指数空间复杂度(O(2^n)):算法所需的额外内存空间随问题规模的增大而以指数级增长。例如,需要存储所有可能的子集或排列。

        需要注意的是,空间复杂度只考虑算法本身所需的额外内存空间,不包括输入数据所占用的存储空间。另外,空间复杂度也可以根据最坏情况或平均情况来进行分析。

O(1) - 常数空间复杂度: 算法的内存使用与输入规模无关,占用固定的内存空间。示例:

def constant_space_algorithm(arr):result = 0for num in arr:result += numreturn result

O(n) - 线性空间复杂度: 算法的内存使用与输入规模成正比。示例:

def linear_space_algorithm(n):arr = [0] * nreturn arr

O(n^2) - 平方空间复杂度: 算法的内存使用与输入规模的平方成正比。示例:

def quadratic_space_algorithm(n):arr = [[0] * n for _ in range(n)]return arr

3 时间复杂度和空间复杂度计算示例

例子1:计算数组中所有元素的和。

def sum_array(arr):sum = 0for num in arr:sum += numreturn sum

时间复杂度:O(n),其中n是数组中的元素数量。遍历数组需要依次访问每个元素一次,因此时间复杂度与数组的大小成线性关系。

空间复杂度:O(1)。算法只使用了一个额外的变量存储累加和,并没有占用随问题规模变化的额外内存。


例子2:快速排序算法。

def quicksort(arr, left, right):if left < right:pivot = partition(arr, left, right)quicksort(arr, left, pivot - 1)quicksort(arr, pivot + 1, right)def partition(arr, left, right):pivot = arr[right]i = left - 1for j in range(left, right):if arr[j] <= pivot:i += 1arr[i], arr[j] = arr[j], arr[i]arr[i + 1], arr[right] = arr[right], arr[i + 1]return i + 1

时间复杂度:最好情况下为O(nlogn),最坏情况下为O(n^2)。快速排序平均情况下的划分操作需要O(n)的时间复杂度,且需要递归n次,因此总体复杂度为O(nlogn)。但在最坏情况下,划分不平衡导致某一边的规模接近n,此时的时间复杂度变为O(n^2)。

空间复杂度:最好情况下为O(logn),最坏情况下为O(n)。快速排序使用递归调用,每次递归调用都需要保存当前函数的堆栈信息,而在最坏情况下,可能需要递归n次,所以空间复杂度为O(n)。而在最好情况下,递归调用树的高度为logn,因此空间复杂度为O(logn)。


例子3:递归实现斐波那契数列。

def fibonacci(n):if n <= 0:return 0if n == 1:return 1return fibonacci(n - 1) + fibonacci(n - 2)
时间复杂度:指数级别,为O(2^n)。由于递归调用会重复计算相同的斐波那契数,时间复杂度呈指数级增长。
空间复杂度:最好和最坏情况下均为O(n),取决于递归调用的最大深度n。每次递归调用都需要在堆栈中保存函数的局部变量和参数,因此空间复杂度为O(n)。 

该代码实现了递归方式计算斐波那契数列的函数。

时间复杂度:指数级别,为 O(2^n)。每次递归调用都会产生两个新的递归调用,因此递归树的总节点数是指数级别的,递归树的深度是 n。所以,总体的时间复杂度是 O(2^n)。

空间复杂度:指数级别,为 O(n)。在递归调用过程中,需要使用栈来保存每次递归调用的参数和局部变量。由于递归树的深度是 n,所以空间复杂度是 O(n)。

需要注意的是,由于斐波那契数列的计算可以通过动态规划或迭代的方式进行优化,以降低时间复杂度和空间复杂度。递归方式计算斐波那契数列在面对较大的 n 值时,会导致非常高的时间和空间消耗。

 例子4:非递归实现的斐波那契数列。

def fibonacci(n):if n <= 0:return 0a = 0b = 1for _ in range(2, n+1):c = a + ba = bb = creturn b

这段代码实现了求解斐波那契数列的函数。

该代码的时间复杂度是 O(n),其中 n 是要计算的斐波那契数的索引。在 for 循环中,需要执行 n-1 次加法操作。因此,时间复杂度是线性级别的。

该代码的空间复杂度是 O(1),因为除了输入参数外,只使用了常数空间来存储变量 a、b 和 c。无论输入的 n 多大,空间占用都是固定的。

例子5:二分查找算法。

def binary_search(arr, target):low = 0                    # 常数时间复杂度high = len(arr) - 1        # 常数时间复杂度while low <= high:mid = (low + high) // 2    # 常数时间复杂度if arr[mid] == target:return midelif arr[mid] < target:low = mid + 1else:high = mid - 1return -1

该算法的时间复杂度为O(logn),在二分查找算法中,每次迭代会将问题规模缩小一半,因此时间复杂度为对数级别。具体而言,时间复杂度是由二分查找的迭代次数决定的。

空间复杂度是 O(1),因为除了输入参数外,没有使用额外的数据结构或变量来存储数据。无论输入规模如何变化,空间占用都是固定的。

例子6:冒泡排序算法。

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]

时间复杂度是 O(n^2),其中 n 是数组 arr 的长度。冒泡排序算法的时间复杂度由两层嵌套循环决定。外层循环执行 n 次,内层循环从 0 到 n-i-1 遍历,其中 i 是外层循环的迭代次数。因此,总的比较次数是 n + (n-1) + (n-2) + ... + 2 + 1,即等差数列求和公式,可以简化为 (n^2 - n) / 2,近似为 n^2。因此,该代码的时间复杂度是 O(n^2)。

该代码的空间复杂度是 O(1),因为除了输入参数外,没有使用额外的数据结构或变量来存储数据。无论输入规模如何变化,空间占用都是固定的。


        计算时间复杂度和空间复杂度通常需要分析算法的每个操作以及它们的频率和内存占用。最终,选择合适的数据结构和算法以及考虑性能优化策略都有助于确保算法在不同规模的问题上都能高效运行。

 

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

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

相关文章

Linux——环境变量

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——环境变量 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;环境变量(environment variables)一般是指在操作系统中用来指定操作…

linux下检测CPU性能的mpstat命令安装与用法

1、安装命令 $ sudo apt-get install sysstat sysstat安装包还包括了检测设备其它状态的命令&#xff0c;查看命令如下&#xff1a; 2、检测CPU命令语法 $ mpstat --h //查看mpstat的语法 Usage: mpstat [ options ] [ <interval> [ <count> ] ] Options are: …

期货基础知识

一、期货是什么&#xff1f;  期货是与现货相对应&#xff0c;并由现货衍生而来。期货通常指期货合约&#xff0c;期货与现货完全不同&#xff0c;现货是实实在在可以交易的货&#xff08;商品&#xff09;&#xff0c;期货主要不是货&#xff0c;而是以某种大众产品如棉花、大…

UG\NX二次开发 获取曲面上指定点位置的uv参数 UF_MODL_ask_face_parm

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 获取曲面上指定点位置的uv参数 UF_MODL_ask_face_parm。 效果: 代码: #include "me.hpp"//parm[2] static void AskFaceUVP…

【插件分享】免费获取ArcGIS国土插件,可一键加载最新亚米级卫星图源

免费获取ArcGIS国土插件&#xff0c;可一键加载最新亚米级卫星图源 国土工具 实用功能国土工具持续更新插件项目实操01 项目占地分析02 shp转txt土地报备坐标03 txt转shp04 在线加载0.5米遥感影像、电子地图服务05 实用工具 如何获取国土工具免费授权第1步第2步第3步 插件下载&…

vscode开发油猴插件环境配置指南

文章目录 一、环境配置1.1油猴插件开始编写代码1.2油猴插件配置1.2.1浏览器插件权限1.2.2插件自身权限 2. 油猴脚本API学习2.1 头文件2.2 油猴API 一、环境配置 1.1油猴插件开始编写代码 在vscode 中写入如下代码‘ // UserScript // name cds_test // namespace …

Java基于SpringBoot+Vue的 4S店车辆管理系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 1 简介2 技术栈3 功能总览4 系统设计4.1 系统设计主要功能4.2 数据库设计4.2.1 数据库设计规范4.2…

论文复现--lightweight-human-pose-estimation-3d-demo.pytorch(单视角多人3D实时动作捕捉DEMO)

分类&#xff1a;动作捕捉 github地址&#xff1a;https://github.com/Daniil-Osokin/lightweight-human-pose-estimation-3d-demo.pytorch 所需环境&#xff1a; Windows10&#xff0c;conda 4.13.0&#xff1b; 目录 conda环境配置安装Pytorch全家桶安装TensorRT&#xff08;…

嘉泰实业:真实低门槛,安全有保障

在互联网金融大行其道的当下&#xff0c;无论用户是多么的青睐、喜爱这种便捷的理财方式&#xff0c;也一定得把资金安全放在心上。要投就投那些实力背景雄厚&#xff0c;诚信经营的平台&#xff0c;可以选择投资用户基数庞大的理财老品牌&#xff0c;也可以选择发展势头迅猛的…

在 Arweave 中轻松管理文件:借助 4EVERLAND 完成 Web3 前端Path Manifests的终极指南

为什么使用Path Manifests&#xff1f; 当在 IPFS 上发布 NFT 时&#xff0c;图片和元数据会被上传到 IPFS 网络以获得一个根 CID&#xff0c;其形式如下&#xff1a; ipfs://bafybeic36ik6cngu37xbzmpytuvyo7z3lyeen44clkkxq5d263zj4nkzr4 通过使用这个根 CID&#xff0c;每…

【性能测试】Jmeter插件之ServerAgent服务器性能监控工具的安装和使用

文章目录 安装插件安装ServerAgent 安装插件 1、在Jmeter官网&#xff1a;https://jmeter-plugins.org/wiki/PluginsManager/ 下载插件管理器Plugins-manager.jar 2、将JAR包放入到lib\ext目录下 3、重启Jmeter&#xff0c;可以在选项下看到Plugins Manager选项 4、安装…

大功率光伏应用不同多电平变换器拓扑的比较研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

java面试题记录

一、多线程、高并发&#xff1a; 1.1 什么是死锁&#xff0c;怎样解决死锁问题&#xff1f; 死锁指的是由于两个或两个以上的线程互相持有对方所需要的资源&#xff0c;同时等待获取对方释放自己所需要的资源&#xff0c;导致这些线程处于等待中而无法往下进行的状态。 精简描述…

计算机二级公共基础知识-2023

计算机基础知识&#xff1a; 计算机的发展&#xff1a; 第一台电子计算机eniac 埃尼阿克 1946 第一台存储程序计算机 edvac 艾迪瓦克 根据电子元器件的发展分类 1.电子管 2.晶体管 3.集成电路 4.超大规模继承电路 按照电脑的用途可以分为 专用计算机 专门用于处理…

CAD ObjectArx 二次开发 创建工具栏实现点击button出现抽屉式菜单

实现在CAD中创建工具栏并添加菜单命令&#xff0c;如下图 参照文章&#xff1a; cad—菜单&#xff0c;工具栏&#xff0c;屏幕菜单&#xff0c;增强工具栏 主要实现路径是通过创建一个可停靠窗口&#xff0c;并在其中创建toolbutton并给button点击事件添加命令&#xff0c;将…

简易yum仓库搭建

目录 一、实验准备 二、获取yum仓库、安装httpd 三、客户机配置yum源 四、测试、验证 一、实验准备 准备两台主机&#xff1a; 192.168.115.148 &#xff1a;安装http 、作为yum仓库、挂载默认光盘 192.168.115.148 &#xff1a;作为客户机使用yum仓库、不挂载光盘 二、…

Spring MVC:请求转发与请求重定向

Spring MVC 请求转发请求重定向附 请求转发 转发&#xff08; forward &#xff09;&#xff0c;指服务器接收请求后&#xff0c;从一个资源跳转到另一个资源中。请求转发是一次请求&#xff0c;不会改变浏览器的请求地址。 简单示例&#xff1a; 1.通过 String 类型的返回值…

【爬虫】8.1. 深度使用tesseract-OCR技术识别图形验证码

深度使用tesseract-OCR技术识别图形验证码 文章目录 深度使用tesseract-OCR技术识别图形验证码1. OCR技术2. 准备工作3. 简单作用了解3.1. 验证码图片爬取-screenshot_as_png3.2. 识别测试-image_to_string3.2.1. 正确识别3.2.2. 错误识别3.2.3. 灰度调节 3.3. 识别实战-使用im…

Trinitycore学习之在vscode查看远端服务器上源码配置

1&#xff1a;安装vscode&#xff0c;去官网下载&#xff0c;这里下载windows版本安装包 .zip https://code.visualstudio.com/Download 2&#xff1a;安装后&#xff0c;安装扩展chinese&#xff0c;使用中文设置&#xff0c;需要重启vscode。 3&#xff1a;安装ssh相关插件…

Jmeter系列进阶-获取图片验证码(4)

安装工具 通过ocrserver工具识别图片验证码&#xff0c;解压后 .exe双击启动即可。 jmeter中使用 &#xff08;1&#xff09;HTTP请求获取验证码 &#xff08;2&#xff09;在获取验证码图片的接口下面添加监听器》保存响应到文件&#xff1b;如下图&#xff1a; &#x…