当前位置: 首页 > news >正文

时间复杂度与空间复杂度的详解

目录

1.时间复杂度

2.时间复杂度计算例题

3.空间复杂度


1.时间复杂度

算法中的基本操作的执行次数,为算法的时间复杂度。
如何表达 时间复杂度?
大O的渐进表示法
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要 大概执行次数,那么这里我们 使用大 O 的渐进表示法。
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O

举例:

 

// 请计算一下 func1 基本操作执行了多少次?
void func1 ( int N ){
int count = 0 ;
for ( int i = 0 ; i < N ; i ++ ) {
for ( int j = 0 ; j < N ; j ++ ) {
count ++ ;
}
}
for ( int k = 0 ; k < 2 * N ; k ++ ) {
count ++ ;
}
int M = 10 ;
while (( M -- ) > 0 ) {
count ++ ;
}
System . out . println ( count );
}

 题解:

Func1 执行的基本操作次数 :
F(N)=N^2+2*N+10;
(1) 用常数1取代运行时间中的所有加法常数。
F(N)=N^2+2*N+1;
(2) 在修改后的运行次数函数中,只保留最高阶项。
F(N)=N^2;
=>O(N^2);

通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。  

另外有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数 ( 上界 )
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数 ( 下界 )
在实际中一般情况关注的是算法的最坏运行情况,如:数组中搜索数据时间复杂度为 O(N)
O(N)中N表示问题的规模

2.时间复杂度计算例题

例题1:

// 计算 func2 的时间复杂度?
void func2 ( int N , int M ) {
int count = 0 ;
for ( int k = 0 ; k < M ; k ++ ) {
count ++ ;
}
for ( int k = 0 ; k < N ; k ++ ) {
count ++ ;
}
System . out . println ( count );
}

答案及分析:

基本操作执行了M+N次,有两个未知数MN,时间复杂度为 O(N+M) 

例题2:

// 计算 func3 的时间复杂度?
void func3 int N ) {
int count = 0 ;
for ( int k = 0 ; k < 100 ; k ++ ) {
count ++ ;
}
System . out . println ( count );
}

 答案及分析:

基本操作执行了100次,通过推导大O阶方法,时间复杂度为 O(1)

 例题3:

// 计算 bubbleSort 的时间复杂度?
void bubbleSort ( int [] array ) {
for ( int end = array . length ; end > 0 ; end -- ) {
boolean sorted = true ;
for ( int i = 1 ; i < end ; i ++ ) {
if ( array [ i - 1 ] > array [ i ]) {
Swap ( array , i - 1 , i );
sorted = false ;
}
}
if ( sorted == true ) {
break ;
}
}
}

 答案及分析:

O(N)中N表示问题的规模

F(N)=N*(N-1)=N^2-N;

通过推导大 O 阶方法 + 时间复杂度一般看最坏,时间 复杂度为 O(N^2)

 例题4:

// 计算 binarySearch 的时间复杂度?
int binarySearch ( int [] array , int value ) {
int begin = 0 ;
int end = array . length - 1 ;
while ( begin <= end ) {
int mid = begin + (( end - begin ) / 2 );
if ( array [ mid ] < value )
begin = mid + 1 ;
else if ( array [ mid ] > value )
end = mid - 1 ;
else
return mid ;
}
return - 1 ;
}

 答案及分析:

方法1:

对于不能直接看出的并较复杂的问题,可以采用数学归纳法

 答案:

 方法2:

 

N/(2^x) =1(x为循环的执行次数)

x的解:

例题 5

// 计算阶乘递归 factorial 的时间复杂度?
long factorial ( int N ) {
return N < 2 ? N : factorial ( N - 1 ) * N ;
}

对于不能直接看出的并较复杂的问题,可以采用数学归纳法,但对于递归我们有专门总结的方法。

F(N)=递归的次数*每次递归代码的执行次数

 答案及分析:

通过计算分析发现基本操作递归了 N次, 每次递归代码的执行次数为1 时间复杂度为O(N)

例题6:

// 计算斐波那契递归 fifibonacci 的时间复杂度?
int fifibonacci ( int N ) {
return N < 2 ? N : fifibonacci ( N - 1 ) + fifibonacci ( N - 2 );
}

  答案及分析:

对于不能直接看出的并较复杂的问题,可以采用数学归纳法(不展开)

面对这种多递归入口的题,可以使用补全法。

何为补全法?

以F4为例

F(N): 

 

1+2+4+……+2^(N-1)
=2^N-1;
O(2^N)

3.空间复杂度

空间复杂度是对一个算法在运行过程中 临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少 bytes 的空 间,因为这个也没太大意义,所以空间复杂度算的是变量的个数
空间复杂度计算规则基本跟时间复杂度类似 ,也 使用 O 渐进表示法
无论什么类型,只看开了多少的空间

 例题1:

// 计算 bubbleSort 的空间复杂度?
void bubbleSort ( int [] array ) {
for ( int end = array . length ; end > 0 ; end -- ) {
boolean sorted = true ;
for ( int i = 1 ; i < end ; i ++ ) {
if ( array [ i - 1 ] > array [ i ]) {
Swap ( array , i - 1 , i );
sorted = false ;
}
}
if ( sorted == true ) {
break ;
}
}
}

   答案及分析:

 使用了常数个额外空间,所以空间复杂度为 O(1)

例题2:

// 计算 fifibonacci 的空间复杂度?
int [] fifibonacci ( int n ) {
long [] fifibArray = new long [ n + 1 ];
fifibArray [ 0 ] = 0 ;
fifibArray [ 1 ] = 1 ;
for ( int i = 2 ; i <= n ; i ++ ) {
fifibArray [ i ] = fifibArray [ i - 1 ] + fifibArray [ i - 2 ];
}
return fifibArray ;
}

 答案及分析:

动态开辟了N个空间,空间复杂度为 O(N)

例题3:

// 计算阶乘递归 Factorial 的空间复杂度?
long factorial ( int N ) {
return N < 2 ? N : factorial ( N - 1 ) * N ;
}

  答案及分析:

递归调用了 N 次,开辟了 N 个栈帧,每个栈帧使用了常数个空间。空间复杂度为 O(N)

 

以上为我个人的小分享,如有问题,欢迎讨论!!! 

都看到这了,不如关注一下,给个免费的赞 

 

 

相关文章:

时间复杂度与空间复杂度的详解

目录 1.时间复杂度 2.时间复杂度计算例题 3.空间复杂度 1.时间复杂度 算法中的基本操作的执行次数&#xff0c;为算法的时间复杂度。 如何表达 时间复杂度&#xff1f; 大O的渐进表示法 实际中我们计算时间复杂度时&#xff0c;我们其实并不一定要计算精确的执行次数&#xf…...

每日一学:什么是 Harbor ?

目录 什么是 Harbor &#xff1f; 一、Harbor 的优势 二、Harbor 架构构成 三、Core services 这是 Harbor 的核心功能 什么是 Harbor &#xff1f; Harbor 是 VMware 公司开源的企业级 Docker Registry 项目&#xff0c;其目标是帮助用户迅速搭建一个企业级的 Docker Reg…...

灰度均衡变换之c++实现(qt + 不调包)

1.基本原理 灰度均衡是以累计分布函数变换为基础的直方图修正法&#xff0c;它可以产生一副灰度级分布概率均匀的图像。也就是说&#xff0c;经过灰度均衡后的图像在没一级灰度上像素点的数量相差不大。公式见下图&#xff0c;为灰度值为x的像素点的个数&#xff0c;n为总像素点…...

flink1.17 自定义trigger ContinuousEventTimeTrigger

在 ContinuousEventTimeTrigger 的基础上新增了timeout,如果超时后窗口都没关闭,那么就硬输出一波,避免间断数据,留存窗口太久. ContinuousEventTimeTrigger ContinuousEventTimeTrigger连续事件时间触发器与ContinuousProcessingTimeTrigger连续处理时间触发器,指定一个固定…...

AIGC:【LLM(五)】——Faiss:高效的大规模相似度检索库

文章目录 一.简介1.1 什么是Faiss1.2 Faiss的安装 二.Faiss检索流程2.1 构建向量库2.2 构建索引2.3 top-k检索 三.Faiss构建索引的多种方式3.1 Flat &#xff1a;暴力检索3.2 IVFx Flat &#xff1a;倒排暴力检索3.3 IVFxPQy 倒排乘积量化3.4 LSH 局部敏感哈希3.5 HNSWx 一.简介…...

自然语言处理从入门到应用——LangChain:记忆(Memory)-[记忆的类型Ⅱ]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 对话知识图谱记忆&#xff08;Conversation Knowledge Graph Memory&#xff09; 这种类型的记忆使用知识图谱来重建记忆&#xff1a; from langchain.memory import ConversationKGMemory from langchain.llms impo…...

桥接模式-java实现

桥接模式 桥接模式的本质&#xff0c;是解决一个基类&#xff0c;存在多个扩展维度的的问题。 比如一个图形基类&#xff0c;从颜色方面扩展和从形状上扩展&#xff0c;我们都需要这两个维度进行扩展&#xff0c;这就意味着&#xff0c;我们需要创建一个图形子类的同时&#x…...

Linux systemd管理常用的几个小案例

systemd是目前Linux系统上主要的系统守护进程管理工具&#xff0c;配置文件要以.service结尾且放到 /usr/lib/systemd/system/目录下面 1、systemd管理ElasticSearch [Unit] DescriptionElasticsearch Service[Service] Typeforking Userelastic Groupelastic ExecStart/home…...

38、IPv6过渡技术

本节内容作为IPv6相关知识的最后一节内容&#xff0c;同时也作为我们本专栏网络层知识的最后一节内容&#xff0c;主要介绍从IPv4地址到IPv6地址过渡的相关技术。在这里我们只学习各类考试中常考的三种技术。 IPv4向IPv6的过渡 在前面的知识中&#xff0c;我们学习到了两种IP地…...

HMMER-序列分析软件介绍

HMMER是一个软件包&#xff0c;它提供了制作蛋白质和DNA序列域家族概率模型的工具&#xff0c;称为轮廓隐马尔可夫模型、轮廓HMM或仅轮廓&#xff0c;并使用这些轮廓来注释新序列、搜索序列数据库以寻找其他同源物&#xff0c;以及进行深度多重序列比对。HMMER是已知蛋白质和DN…...

【项目学习1】如何将java对象转化为XML字符串

如何将java对象转化为XML字符串 将java对象转化为XML字符串&#xff0c;可以使用Java的XML操作库JAXB&#xff0c;具体操作步骤如下&#xff1a; 主要分为以下几步&#xff1a; 1、创建JAXBContext对象&#xff0c;用于映射Java类和XML。 JAXBContext jaxbContext JAXBConte…...

nginx负载均衡

负载均衡&#xff1a;反向代理来实现 正向代理的配置方法。 1、NGINX的七层代理和四层代理&#xff1a; 七层是最常用的反向代理方式&#xff0c;只能配置在nginx配置文件的http模块。而且配置方法名称&#xff1a;upstream 模块&#xff0c;不能写在server中&#xff0c;也…...

【毕业项目】自主设计HTTP

博客介绍&#xff1a;运用之前学过的各种知识 自己独立做出一个HTTP服务器 自主设计WEB服务器 背景目标描述技术特点项目定位开发环境WWW介绍 网络协议栈介绍网络协议栈整体网络协议栈细节与http相关的重要协议 HTTP背景知识补充特点uri & url & urn网址url HTTP请求和…...

关于安卓jar包修改并且重新发布

背景&#xff1a; 对于某些jar包&#xff0c;其内部是存在bug的&#xff0c;解决的方法无外乎就有以下几种方法&#xff1a; &#xff08;1&#xff09;通过反射&#xff0c;修改其赋值逻辑 &#xff08;2&#xff09;通过继承&#xff0c;重写其方法 &#xff08;3&#xff0…...

Java课题笔记~ AspectJ 对 AOP 的实现(掌握)

AspectJ 对 AOP 的实现(掌握) 对于 AOP 这种编程思想&#xff0c;很多框架都进行了实现。Spring 就是其中之一&#xff0c;可以完成面向切面编程。然而&#xff0c;AspectJ 也实现了 AOP 的功能&#xff0c;且其实现方式更为简捷&#xff0c;使用更为方便&#xff0c;而且还支…...

npm 报错 cb() never called!

不知道有没有跟我一样的情况&#xff0c;在使用npm i的时候一直报错&#xff1a;cb() never called! 换了很多个node版本&#xff0c;还是不行&#xff0c;无法解决这个问题 百度也只是让降低node版本请缓存&#xff0c;gpt给出的解决方案也是同样的 但是缓存清过很多次了&a…...

finally有什么作用以及常用场景

在Java中&#xff0c;finally是一个关键字&#xff0c;用于定义一个代码块&#xff0c;该代码块中的代码无论是否发生异常都会被执行。finally块通常用于确保在程序执行过程中资源的释放和清理。 使用场景&#xff1a; 1. 资源释放&#xff1a;finally块经常用于释放打开的资…...

Python web实战之Django URL路由详解

概要 技术栈&#xff1a;Python、Django、Web开发、URL路由 Django是一种流行的Web应用程序框架&#xff0c;它采用了与其他主流框架类似的URL路由机制。URL路由是指将传入的URL请求映射到相应的视图函数或处理程序的过程。 什么是URL路由&#xff1f; URL路由是Web开发中非常…...

10-数据结构-队列(C语言)

队列 目录 目录 队列 一、队列基础知识 二、队列的基本操作 1.顺序存储 ​编辑 &#xff08;1&#xff09;顺序存储 &#xff08;2&#xff09;初始化及队空队满 &#xff08;3&#xff09;入队 &#xff08;4&#xff09;出队 &#xff08;5&#xff09;打印队列 &…...

面试之快速学习C++11 - 右值 移动构造 std::move

C11右值引用 字面意思&#xff0c;以引用传递的方式使用c右值左值和右值&#xff0c;左值是lvalue loactor value 存储在内存中&#xff0c;有明确存储地址的数据&#xff0c; 右值rvalue read value , 指的是那些可以提供数据值的数据&#xff08;不一定可以寻址&#xff0c;…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...