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

【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数据结构 空间复杂度】

最近太忙了都好久没有更新博客了,太难了,抽空水一篇文章,大佬们多多支持. 上篇:时间复杂度分析 目录 前言 一、空间复杂度概念&#xff1f; 二、实例展示 三、.有复杂度要求的算法题练习 1.题目链接&#xff1a;力扣--消失的数字 2.题目链接&#xff1a;力扣--旋转数组 总结: 1…...

多数据库管理工具哪家强?ChatGPT点评,第一位并不是Navicat

SQL逐渐成为职场必备的编程语言&#xff0c;相信大家都不陌生。SQL是一种结构化查询语言&#xff0c;是用于数据库之间通信的编程语言。每个数据库都有着自己独特的访问规则&#xff0c;但大体上是遵循SQL标准。 因此&#xff0c;辗转于不同的数据库之间&#xff0c;开发者或D…...

UnityShader常用函数(UnityShader内置函数、CG和GLSL内置函数等)

空间变换函数函数名描述float4 UnityWorldToClipPos(float3 pos )把世界坐标空间中某一点pos变换到齐次裁剪空间float4 UnityViewToClipPos(float3 pos )把观察坐标空间中某一点pos变换到齐次裁剪空间float3 UnityObjectToViewPos(float3 pos或float4 pos)模型局部空间坐标系中…...

Springboot自定义注解-1

注解用于修饰其他的注解(纪委&#xff1a;管干部的干部) ① Retention&#xff1a;定义注解的保留策略 Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中&#xff0c;在class字节码文件中不包含 Retention(RetentionPolicy.CLASS) …...

经纬度标定及大地坐标系相关概念(一)

经纬度标定及大地坐标系相关概念&#xff08;一&#xff09;一、背景二、经纬度的概念三、大地坐标系四、大地坐标系的分类五、各类坐标系介绍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、基本特点 基于锁策略&#xff0c;可以知道synchronized具有以下特性&#xff1a; 1.开始时候是乐观锁&#xff0c;如果锁冲突频繁就转换为悲观锁 2.开始是轻量级锁&#xff0c;如果锁持有的时间较长&#xff0c;就转换成重量级锁 3.实现轻量级锁的时候…...

面试被问死怎么办?学会这四招,通过的机率提升30%

软件工程师面试很难&#xff0c;难到什么程度呢&#xff1f;有一句话可以来形容&#xff1a; 面试造飞机&#xff0c;上班拧螺丝 没错&#xff0c;面试的时候各种问你原理、机制&#xff0c;而这些在实际工作中却很难用到。于是乎&#xff0c;很多工程师面试的时候就非常害怕…...

Android TV UI开发常用知识

导入依赖 Google官方为Android TV的UI开发提供了一系列的规范组件&#xff0c;在leanback的依赖库中&#xff0c;这里介绍一些常用的组件&#xff0c;使用前需要导入leanback库。 implementation androidx.leanback:leanback:$version常用的页面 这些Fragment有设计好的样式&…...

Xshell 下载及安装

文章目录下载安装连接服务器Xshell 是一个强大的安全终端模拟软件&#xff0c;它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 Xshell可以在Windows界…...

【LeetCode】剑指 Offer(12)

目录 题目&#xff1a;剑指 Offer 30. 包含min函数的栈 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 30. 包含m…...

vue在history模式下打包部署问题解决

引言 项目使用的模板是element-template&#xff0c;由于业务需要&#xff0c;我将路由的hash模式更改为了history模式&#xff0c;然后在打包部署项目时就出现了问题 个人发现是资源的访问路径有问题&#xff0c;在部署之后发现每次访问的js资源路径前都会自动携带上我路由的…...

Java中常见性能优化策略的总结

文章目录1. 代码优化2. 数据库层面优化SQL调优架构层面的调优连接池调优3. 网络优化4. 缓存缓存分类使用场景选型考虑什么时候更新缓存&#xff1f;如何保障更新的可靠性和实时性&#xff1f;缓存是否会满&#xff0c;缓存满了怎么办&#xff1f;缓存是否允许丢失&#xff1f;丢…...

c++日志库log4cplus使用

项目中需要打印log&#xff0c;方便程序调试和问题定位分析。C实现的log4cplus日志库是一种易于使用的C 日志记录API&#xff0c;可提供线程安全&#xff0c;灵活且任意粒度的日志管理和配置控制。 下面介绍一下在linux中安装log4cplus库过程 下载地址&#xff1a;https://gi…...

什么是接口测试,我们如何实现接口测试?

1. 什么是接口测试 顾名思义&#xff0c;接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型&#xff0c;测试类型又主…...

随机森林在sklearn中的实现

目录 一.集成算法 二.sklearn中的集成算法模块ensemble 三.RandomForestClassifier(随机森林分类器) 四.重要参数 1.基评估器参数 2.随机森林参数 五.重要属性和接口 六.Bagging的另一个必要条件 七.RandomForestRegressor(随机森林回归器) 八.机器学习中调参的基本思…...

[论文总结] 深度学习在农业领域应用论文笔记11

深度学习在农业上的应用笔记11 最近发表的相关论文数量不多&#xff0c;质量普遍也不尽如人意&#xff0c;尤其是《Computers and Electronics in Agriculture》这个期刊。这些论文的方法都很简单&#xff0c;只是强行将深度学习应用于某个问题上&#xff0c;而没有考虑到农业…...

Android 9.0 SystemUI 状态栏屏蔽弹出的悬浮式通知

1.概述 在9.0的系统ROM产品定制化开发中,在systemui的状态栏中,会在有闹钟 wifi连接等特殊弹窗通知的时候,会在接收到系统通知时,弹窗悬浮式弹窗通知,然后过几秒中, 就消失了,所以像这样的悬浮式通知,在有些产品中是不需要的,要求屏蔽掉,这就需要按照悬浮式流程来分析…...

商简智能计划与排程SPS在纺织行业中的应用

企业背景 某织造、染色及后整理一体化工艺的纺织面料企业&#xff0c;主要从事户外功能运动服装、内衣、泳衣、汽车内饰等面料的研发和销售&#xff0c;年产值在20亿左右&#xff0c;是迪卡侬运动面料最优质供应商之一。 纺织行业特点 印染具有典型的流程行业特性&#xff0c…...

549、RocketMQ详细入门教程系列 -【消息队列之 RocketMQ(三)】 2023.02.28

目录一、Spring 整合 RocketMQ1.1 消息生产者1.2 消息消费者1.3 Spring 配置文件1.4 运行实例程序二、参考链接一、Spring 整合 RocketMQ 不同于 RabbitMQ、ActiveMQ、Kafka 等消息中间件&#xff0c;Spring 社区已经通过多种方式提供了对这些中间件产品集成&#xff0c;例如通…...

如何使用SpringBoot ⽇志?

Spring Boot自定义日志的打印:在一个类中先获取到打印日志对象&#xff08;日志框架提供的日志对象&#xff0c;而日志框架默认已经集成到Spring Boot里了&#xff0c;springboot默认使用 slf4jlogback);注意&#xff1a;得到日志对象Logger ->来自于slf4j2、使用目志对象提…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

Windows 下端口占用排查与释放全攻略

Windows 下端口占用排查与释放全攻略​ 在开发和运维过程中&#xff0c;经常会遇到端口被占用的问题&#xff08;如 8080、3306 等常用端口&#xff09;。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口&#xff0c;帮助你高效解决此类问题。​ 一、准…...

数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)

目录 &#x1f50d; 若用递归计算每一项&#xff0c;会发生什么&#xff1f; Horners Rule&#xff08;霍纳法则&#xff09; 第一步&#xff1a;我们从最原始的泰勒公式出发 第二步&#xff1a;从形式上重新观察展开式 &#x1f31f; 第三步&#xff1a;引出霍纳法则&…...