【Day02数据结构 空间复杂度】
最近太忙了都好久没有更新博客了,太难了
,抽空水一篇文章,大佬们多多支持.
上篇:时间复杂度分析
目录
前言
一、空间复杂度概念?
二、实例展示
三、.有复杂度要求的算法题练习
1.题目链接:力扣--消失的数字
2.题目链接:力扣--旋转数组
总结:
1.空间复杂度
2.有关空间复杂度的OJ题
前言
上节我们学习了算法的时间复杂度,今天来学习空间复杂度.
一、空间复杂度概念?
老规矩先上定义:
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。前一篇关于时间复杂度我们知道 计算空间复杂度并不是计算算法的执行时间,算的是算法的执行次数,而空间复杂度同理,不算空间,算的是变量的个数.它同样和时间复杂度一样是一个估算,与时间复杂度的规定大同小异.
二、实例展示
1.冒泡排序:
// 计算BubbleSort的空间复杂度?
void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i-1] > a[i]){Swap(&a[i-1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}
解析:空间复杂度也是用大O渐进法,类似于时间复杂度的方式,是去计算变量的个数, 如上冒泡排序的空间复杂度是O(1) ,变量有 a,n,szie_t end,size_t i,exchange.总共是常数5个,常数都看作是 1,所以空间复杂度是O(1).
这里我们要注意,时间是可以累计的,而空间是不累计的,也就是说时间用完了还存在,而空间被开辟后用完可以丢弃销毁,比如:一个循环走了N次,它重复利用的是一个空间.用不到了就可以被销毁;递归同样也是一个道理,在递归时开辟了一块又一块的空间,当计算往下走时,保留空间,返回时,用不到的空间就会被销毁.
2.斐波那契数:
// 计算Fibonacci的空间复杂度?
long long* Fibonacci(size_t n)
{if(n==0)return NULL;long long * fibArray = (long long *)malloc((n+1) * sizeof(long long));fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n ; ++i){fibArray[i ] = fibArray[ i - 1] + fibArray [i - 2];}return fibArray ;
}
解析:(malloc的意思是开辟了 n+1 个 long long 类型变量的数组).
计算变量个数有 n, fibArray, fibArray[0], fibArray[1], i 一共 5 个,但是我们还看见 malloc 函数中有 (n+1) ,所以空间复杂度是 O(N+6) ,随着N的增大, +6 的影响对其影响不大,所以可以忽略不计,最后斐波那契数的空间复杂度是 O(N) .
(大多数情况下,算法的空间复杂度都是O(1),都是常数个变量,此代码中 malloc 是开辟了一个数组.)
3.阶乘递归:
// 计算阶乘递归Factorial的空间复杂度?
long long Factorial(size_t N)
{return N < 2 ? N : Factorial(N-1)*N;
}
解析: 这个代码我们知道,递归调用了 N 次,每一次都调用建立一个栈帧,每个栈帧使用了常数个空间,也就是一次递归的空间复杂度是 O(1) ,而调用了 N 次递归,空间复杂度就是 O(N) .
(虽然递归调用返回时空间销毁,但是我们仍要计算它,可以理解为计算时间复杂度的最坏情况,)
三、.有复杂度要求的算法题练习
1.题目链接:力扣--消失的数字

思路一:
数组nums包含 0 ~ n 的所有整数,要找出其中缺的那一个数字,我们按将其数组元素进行排序,例如: [2 ,3, 1, 4, 5, 7, 6, 9],将其排序之后就会变成[1,2,3,4,5,6,7,9].然后就很简单了,要找到消失的数就可以将排序后的元素遍历一遍,看后一个数是不是比前一个数大1,如果不是那就直接找到了.
代码如下:
int missingNumber(int* nums, int numsSize){for(int i = numsSize - 1; i > 0; i--){//冒泡排序flag = 1;for(int j = 0; j < i; j++){if(nums[i] > nums[i + 1]){int tmp = nums[i];nums[i] = nums[i + 1];nums[i + 1] = tmp;if(flag)flag = 0;}if(flag)break;}}//检查每个元素前后是否相差为1for(int z = 0; z < numsSize - 2; z++){if(nums[z + 1] - nums[z] != 1)return nums[z + 1] - 1;} //考虑头尾if(nums[0])return 0;return numsSize;
}
但是题目要求算法的时间复杂度要求是 O(N) ,如果使用最快的排序只能达到O(N*logN),所以排序并不合适.
思路二:
要求 0 ~ n 中缺失的那个,可以将 0 ~ n 的所有元素相加,得到的结果再与原数组里元素的和相减,结果就得到消失的数字.
代码如下:
int missingNumber(int* nums, int numsSize){int misNum = 0;for(int j = 0; j < numsSize + 1; j++)misNum += j;for(int i = 0; i < numsSize; i++)misNum -= nums[i];return misNum;
}
思路三:
异或:将数组中的数依次跟 0 ~ n 的所有数异或,最后剩下的数据就是缺的那个数字(异或:按位异或相同为 0 ,不同为 1 ).
举例如下:
我们知道相同的数异或到一起就没了,是0. 此题如果把 0 ~ n 的数与原数组里的元素进行异或,然后相同的两个数异或没了,那么剩下的就是消失的那个数,(两数组进行异或时不需要有序,因为异或满足交换律,相同的会消失,最后剩下的就是要求的数)
举例验证:
这个例子我们可以看到虽然数据没有有序,但是相同的两个数被相互消去,得到的是不同的那个数.
代码如下:
int missingNumber(int* nums, int numsSize){int x = 0;//用for循环求出数组中的异或之和for(int i = 0; i < numsSize; i++)x ^= nums[i];for(int j = 0; j < numsSize + 1; j++)//原数组比0~n少1个数,要+1//再和(0~n)之间的数异或x ^= j;return x;
}
2.题目链接:力扣--旋转数组

思路一:
如果要进行一次旋转,有数组 [1,2,3,4,5,6,7,8,9] ,可以先将数组中的最后末尾元素 9 存放到一个变量中,然后将最后一个元素之前的数据依次向后挪动,我们可以定义一个变量 end ,将它依次减减,就可以将元素依次挪动,直到最后首元素空出,再将 9 放进去,这样就完成了旋转了一次,
代码如下:
void rotate(int* nums, int numsSize, int k)
{for(int i=0;i<k;++i ){//旋转一次int tmp=0;tmp=nums[numsSize-1];for(int end=numsSize-2;end>=0;end--){nums[end+1]=nums[end];}nums[0]=tmp;}
}
当前代码的时间复杂度是O(N*K),效率太低.
思路二:
以空间换时间:创建一个新的数组,首先将后 k 个数放到新数组的前 k 项里面,然后再将剩下的数放到新数组里面,(也就是将原数组分两段存放到一个新的数组中)
最后第二个循环是将新数组的内容替换掉原数组中的内容
代码如下:
void rotate(int* nums, int numsSize, int k){int nums1[numsSize];for(int i=0;i<numsSize;i++){nums1[(i+k)%numsSize]=nums[i];}for(int j=0;j<numsSize;j++){nums[j]=nums1[j];}
}
numsSize取余是为了防止k的大小长度超过numsSize, 这样的解法时间复杂度符合要求,但是需要额外的空间实现
思路三:
有数组 [1,2,3,4,5,6,7]
先将数组的后 k 个逆置: [1,2,3,4,7,6,5]
再将前 n - k 个逆置: [4,3,2,1,7,6,5]
再整体逆置:[5,6,7,1,2,3,4]
代码如下:
void Reverse(int* nums, int left, int right)
{while (left < right){int tmp = nums[left];nums[left] = nums[right];nums[right] = tmp;++left;--right;}
}
void rotate(int* nums, int numsSize, int k)
{if (k >= numsSize){k %= numsSize;}Reverse(nums, numsSize - k, numsSize - 1);Reverse(nums, 0 , numsSize -k - 1);Reverse(nums, 0 , numsSize - 1);}
总结:
1.空间复杂度
2.有关空间复杂度的OJ题
仓促之下水的文章,码文不易,各位看官给个三连呗,如有不足还望指出.
相关文章:
【Day02数据结构 空间复杂度】
最近太忙了都好久没有更新博客了,太难了,抽空水一篇文章,大佬们多多支持. 上篇:时间复杂度分析 目录 前言 一、空间复杂度概念? 二、实例展示 三、.有复杂度要求的算法题练习 1.题目链接:力扣--消失的数字 2.题目链接:力扣--旋转数组 总结: 1…...
多数据库管理工具哪家强?ChatGPT点评,第一位并不是Navicat
SQL逐渐成为职场必备的编程语言,相信大家都不陌生。SQL是一种结构化查询语言,是用于数据库之间通信的编程语言。每个数据库都有着自己独特的访问规则,但大体上是遵循SQL标准。 因此,辗转于不同的数据库之间,开发者或D…...
UnityShader常用函数(UnityShader内置函数、CG和GLSL内置函数等)
空间变换函数函数名描述float4 UnityWorldToClipPos(float3 pos )把世界坐标空间中某一点pos变换到齐次裁剪空间float4 UnityViewToClipPos(float3 pos )把观察坐标空间中某一点pos变换到齐次裁剪空间float3 UnityObjectToViewPos(float3 pos或float4 pos)模型局部空间坐标系中…...
Springboot自定义注解-1
注解用于修饰其他的注解(纪委:管干部的干部) ① Retention:定义注解的保留策略 Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含 Retention(RetentionPolicy.CLASS) …...
经纬度标定及大地坐标系相关概念(一)
经纬度标定及大地坐标系相关概念(一)一、背景二、经纬度的概念三、大地坐标系四、大地坐标系的分类五、各类坐标系介绍5.1 我国地理坐标系5.1.1 北京54坐标系5.1.2 1980西安坐标系5.1.3 2000国家大地坐标系5.2 世界大地坐标系5.1.1 WGS84坐标系5.3 加密坐…...
synchronized关键字原理
synchronized原理 1、基本特点 基于锁策略,可以知道synchronized具有以下特性: 1.开始时候是乐观锁,如果锁冲突频繁就转换为悲观锁 2.开始是轻量级锁,如果锁持有的时间较长,就转换成重量级锁 3.实现轻量级锁的时候…...
面试被问死怎么办?学会这四招,通过的机率提升30%
软件工程师面试很难,难到什么程度呢?有一句话可以来形容: 面试造飞机,上班拧螺丝 没错,面试的时候各种问你原理、机制,而这些在实际工作中却很难用到。于是乎,很多工程师面试的时候就非常害怕…...
Android TV UI开发常用知识
导入依赖 Google官方为Android TV的UI开发提供了一系列的规范组件,在leanback的依赖库中,这里介绍一些常用的组件,使用前需要导入leanback库。 implementation androidx.leanback:leanback:$version常用的页面 这些Fragment有设计好的样式&…...
Xshell 下载及安装
文章目录下载安装连接服务器Xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 Xshell可以在Windows界…...
【LeetCode】剑指 Offer(12)
目录 题目:剑指 Offer 30. 包含min函数的栈 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:剑指 Offer 30. 包含m…...
vue在history模式下打包部署问题解决
引言 项目使用的模板是element-template,由于业务需要,我将路由的hash模式更改为了history模式,然后在打包部署项目时就出现了问题 个人发现是资源的访问路径有问题,在部署之后发现每次访问的js资源路径前都会自动携带上我路由的…...
Java中常见性能优化策略的总结
文章目录1. 代码优化2. 数据库层面优化SQL调优架构层面的调优连接池调优3. 网络优化4. 缓存缓存分类使用场景选型考虑什么时候更新缓存?如何保障更新的可靠性和实时性?缓存是否会满,缓存满了怎么办?缓存是否允许丢失?丢…...
c++日志库log4cplus使用
项目中需要打印log,方便程序调试和问题定位分析。C实现的log4cplus日志库是一种易于使用的C 日志记录API,可提供线程安全,灵活且任意粒度的日志管理和配置控制。 下面介绍一下在linux中安装log4cplus库过程 下载地址:https://gi…...
什么是接口测试,我们如何实现接口测试?
1. 什么是接口测试 顾名思义,接口测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型,测试类型又主…...
随机森林在sklearn中的实现
目录 一.集成算法 二.sklearn中的集成算法模块ensemble 三.RandomForestClassifier(随机森林分类器) 四.重要参数 1.基评估器参数 2.随机森林参数 五.重要属性和接口 六.Bagging的另一个必要条件 七.RandomForestRegressor(随机森林回归器) 八.机器学习中调参的基本思…...
[论文总结] 深度学习在农业领域应用论文笔记11
深度学习在农业上的应用笔记11 最近发表的相关论文数量不多,质量普遍也不尽如人意,尤其是《Computers and Electronics in Agriculture》这个期刊。这些论文的方法都很简单,只是强行将深度学习应用于某个问题上,而没有考虑到农业…...
Android 9.0 SystemUI 状态栏屏蔽弹出的悬浮式通知
1.概述 在9.0的系统ROM产品定制化开发中,在systemui的状态栏中,会在有闹钟 wifi连接等特殊弹窗通知的时候,会在接收到系统通知时,弹窗悬浮式弹窗通知,然后过几秒中, 就消失了,所以像这样的悬浮式通知,在有些产品中是不需要的,要求屏蔽掉,这就需要按照悬浮式流程来分析…...
商简智能计划与排程SPS在纺织行业中的应用
企业背景 某织造、染色及后整理一体化工艺的纺织面料企业,主要从事户外功能运动服装、内衣、泳衣、汽车内饰等面料的研发和销售,年产值在20亿左右,是迪卡侬运动面料最优质供应商之一。 纺织行业特点 印染具有典型的流程行业特性,…...
549、RocketMQ详细入门教程系列 -【消息队列之 RocketMQ(三)】 2023.02.28
目录一、Spring 整合 RocketMQ1.1 消息生产者1.2 消息消费者1.3 Spring 配置文件1.4 运行实例程序二、参考链接一、Spring 整合 RocketMQ 不同于 RabbitMQ、ActiveMQ、Kafka 等消息中间件,Spring 社区已经通过多种方式提供了对这些中间件产品集成,例如通…...
如何使用SpringBoot ⽇志?
Spring Boot自定义日志的打印:在一个类中先获取到打印日志对象(日志框架提供的日志对象,而日志框架默认已经集成到Spring Boot里了,springboot默认使用 slf4jlogback);注意:得到日志对象Logger ->来自于slf4j2、使用目志对象提…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
负载均衡器》》LVS、Nginx、HAproxy 区别
虚拟主机 先4,后7...
SDU棋界精灵——硬件程序ESP32实现opus编码
一、 音频处理框架 该项目基于Espressif的音频处理框架构建,核心组件包括 ESP-ADF 和 ESP-SR,以下是完整的音频处理框架实现细节: 1.核心组件 (1) 音频前端处理 (AFE - Audio Front-End) main/components/audio_pipeline/afe_processor.c功能: 声学回声…...



