数据结构与算法02 - 复杂度

1、空间复杂度

  • 空间复杂度指的是临时占用存储空间大小的量度;
  • 空间复杂度计算的是变量的个数,也采用大O渐进表示法;
  • 由于函数在运行的时候所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译器已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定!

示例1:冒泡排序

void BubbleSort(int* a, int n)
{assert(a);for (size_t end = 0; end > 1; --end){int exchange = 0;for (size_t i = 0; i < end; ++i){if (a[i-1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange = 0);break;}}

这里只创建了3个变量,为常数个,因此空间复杂度为O(1)。

示例2:斐波那契数列1

long long* Fibonacci(size_t n)
{if (n == 0)return Fibonacci;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;
}

 其空间复杂度为O(n);

示例3:递归

long long Fac(size_t N)
{if (0 == N)return 1;return Fac(N - 1) * N;}

累计调用Fac从Fac(N) ~ Fac(0)共调用n + 1次(要创建函数栈帧),因此空间复杂度为O(n)

下面F1()和F2()打印的值一样吗?

void F1()
{int b = 0;printf("%p\n",&b);
}void F2()
{int a = 0;printf("%p\n",&a);
}int main()
{F1();F2();return 0;
}

Vs下打印的结果相同,在同一块区域进行相同的函数栈帧的创建和销毁!

示例4:斐波那契数列2(加法)

long long Fib(size_t N)
{if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2);
}

空间复杂度为:O(N)

原因:递归的过程中空间是不断创造和销毁的过程,调用Fib()时先在一侧调用完后返回,此时空间被销毁,然后再重新创建新的空间的过程!

GTP解释:

  • 1. 递归栈空间

    在递归算法中,空间复杂度通常与递归调用的深度有关。每次进行递归调用时,程序会为当前函数调用分配一个栈帧,栈帧会记录函数调用的参数、返回地址和局部变量等信息。

    对于 Fibonacci 函数:

  • 在最坏的情况下,递归深度会达到 N(例如 Fib(N) 需要调用 Fib(N-1) 和 Fib(N-2),一直递归下去),最深的时候调用栈的深度是 N
  • 2. 空间复杂度的计算
  • 因此,空间复杂度是 O(N),这是因为在递归过程中最深的栈帧深度为 N,而且每个栈帧占用的空间是常量级别的。

时间不可重复利用,空间可以重复利用!

示例5:转轮数组

. - 力扣(LeetCode)

直接旋转暴力求解无法通过!

解法一:

解决代码:

void reverse(int* nums,int begin,int end)
{while(begin < end){int tmp = nums[begin];nums[begin] = nums[end];nums[end] = tmp;++begin;--end;}}
void rotate(int* nums, int numsSize, int k) {if (k > numsSize)k = k%numsSize;reverse(nums,0,numsSize-1-k);reverse(nums,numsSize-k,numsSize-1);reverse(nums,0,numsSize-1);}

把++/--放在前面!

这个代码的时间复杂度为O(N),空间复杂度为O(1)

线上OJ分为两种:

  • IO型:通过scanf输入条件,结果通过printf输出,实现一个完整的程序
  • 接口型:输入条件,参数,结果,返回值返回,实现一个函数,只有部分程序
  • 编译错误指的是语法错误,运行错误不通过可能是由于时间复杂度

 解法二:以空间换时间

创建一块空间,将后k个拷贝到前面去,将前k个拷贝到后面去!(1G大概为10亿字节)

示例代码:

void rotate(int* nums, int numsSize, int k){if (k > numsSize)k = k%numsSize;int* tmp = (int*)malloc(sizeof(int)*numsSize);memcpy(tmp,nums + numsSize -k,sizeof(int)*k);memcpy(tmp+k,nums,sizeof(int)*(numsSize-k));memcpy(nums,tmp,sizeof(int)*numsSize);
}free(tmp);tmp = NULL;

时间复杂度和空间复杂度都为O(N)!

二、顺序表和链表

1、线性表

线性表是n个具有相同特征的数据元素的有限序列!

常见的线性表有:顺序表、链表、栈、队列、字符串

线性表在逻辑上是线性结构,也就是连续的一条直线,但是物理结构(内存中存储)不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储!

2、顺序表

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

顺序表一般分为:静态顺序表和动态顺序表

1、静态顺序表:使用定长数组存储元素;

typedef int SLDataType;
#define N 100000struct SeqList
{SLDateType a[N];int size;
}

2、动态顺序表:使用动态开辟的数组存储;

typedef int SLDataType;typedef struct SeqList
{SLDataType* a;int size;       //有效数据个数int capacity;   //空间容量
}SL;

typeef struct SeqList的意思为:将struct SeqList重命名为SL!

有效数据个数 = 空间容量的时候!进行扩容!

对数据的操作分四种:增删查改

void SeqList(SL s);    // 初始化
void SeqDestory(Sl s);  // 删除

全局变量会自己初始化(不初始化也不会报错);局部变量需要自己进行初始化!

需要注意的是,写顺序表初始化的时候,需要传入的是结构体的地址!这样子才能对传入的结构体进行改变,否则只是对临时拷贝的结构体进行改变。

凡是看到错误:无法解析符号 ---- 只有声明没有定义!

顺序表的销毁:将空间释放,然后将指针置为空,再将有效字节和空间大小设置为0;

free空间的时候只能从该空间的起始位置释放,如果从中间位置或者空指针释放会报错!

尾删的时候不能释放单个空间!(创建的空间只能一起释放!)

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

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

相关文章

Kafka【十二】消费者拉取主题分区的分配策略

【1】消费者组、leader和follower 消费者想要拉取主题分区的数据&#xff0c;首先必须要加入到一个组中。 但是一个组中有多个消费者的话&#xff0c;那么每一个消费者该如何消费呢&#xff0c;是不是像图中一样的消费策略呢&#xff1f;如果是的话&#xff0c;那假设消费者组…

Docker容器创建时,无法访问镜像源:Could not connect to archive.ubuntu.com:80

1.问题描述 当基于dockerfile创建容器时&#xff0c;遇到Could not connect to ...、Failed to fetch ...等异常时&#xff0c;大概原因是没有配置好容器创建所需的镜像源。这里以Ubuntu基础镜像源为例。 dockerfile内容 FROM ubuntu RUN apt update && apt install…

MySQL 锁分类有哪些?一文带你详解!!

MySQL 锁 全局锁全局锁的应用场景全局锁的缺点 表级锁表锁元数据&#xff08;MDL&#xff09;锁MDL 锁的问题 意向锁AUTO-INC 锁 行级锁记录锁&#xff08;Record Lock&#xff09;间隙锁&#xff08;Gap Lock&#xff09;临键锁&#xff08;Next-Key Lock&#xff09;插入意向…

Opencv中的直方图(2)计算图像的直方图函数calcHist()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算一组数组的直方图。 函数 cv::calcHist 计算一个或多个数组的直方图。用于递增直方图bin的元组的元素是从相同位置的相应输入数组中获取的。…

vue多环境配置和打包

件名的后缀来指定它们仅在特定模式下被加载。 .env&#xff1a;所有环境下都会加载的通用配置。 .env.local&#xff1a;本地覆盖配置&#xff0c;不加入版本控制。 .env.[mode]&#xff1a;仅为指定的模式加载的配置文件&#xff0c;例如.env.development、.env.production、…

Cursor是什么?Cursor Pro Plus 如何订阅升级教程

一、Cursor是什么&#xff1f; Cursor 是一个基于 Visual Studio Code&#xff08;VS Code&#xff09;技术构建的高级代码编辑器&#xff0c;专为提高编程效率并更深度地整合 AI 功能而设计。它不仅继承了 VS Code 的强大功能和用户界面&#xff0c;还增加了专门针对 AI 支持…

Agent(智能体)和 MetaGPT,一句话实现整个需求应用代码

前面 2 篇文章&#xff0c;我们使用文生文、文生图和文生音频三个大模型共同实现了图文并茂的儿童绘本故事和绘本故事音频需求&#xff1a; 第一篇 根据主题生成儿童绘本故事&#xff1a;GLM-4-Flash 大模型 API 免费了&#xff0c;手把手构建“儿童绘本”应用实战&#xff08…

Nuxt3入门:过渡效果(第5节)

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 Nuxt 利用 Vue 的 <Transition> 组件在页面和布局之间应用过渡效果。 一、页面过渡效果 你可以启用页面过渡效果&#xff0c;以便对所有页面应用自动过渡效果。 nuxt.config.js export defaul…

概率DP (由一道绿题引起的若干问题。目前为一些老题,蒟蒻的尝试学习1.0)

概率DP&#xff1a; 利用动态规划去解决 概率 期望 的题目。 概率DP 求概率&#xff08;采用顺推&#xff09; 从 初始状态推向结果&#xff0c;同一般的DP类似&#xff0c;只是经历了概率论知识的包装。 老题&#xff1a; 添加链接描述 题意&#xff1a; 袋子里有w只白鼠&am…

linux编译器——gcc/g++

1.gcc linux上先要安装&#xff0c; sudo yum install gcc gcc --version 可以查看当前的版本 &#xff0c;我们默认安装的是4.8.5的版本&#xff0c;比较低&#xff0c; gcc test.c -stdc99 可以使他支持更高版本的c标准 -o 可以殖指明生成文件的名字&#xff0c;可以自己…

上海市计算机学会竞赛平台2024年7月月赛丙组求和问题

题目描述 给定 nn 个整数 a1,a2,…,ana1​,a2​,…,an​&#xff0c;请问这个序列最长有多少长的前缀&#xff0c;满足元素的和大于或等于 00&#xff1f;如果任何长度大于 00 的前缀之和都为负数&#xff0c;则输出 00 输入格式 第一行&#xff1a;单个整数表示 nn第二行&a…

经验笔记:JSP(JavaServer Pages)

JSP&#xff08;JavaServer Pages&#xff09;经验笔记 JSP&#xff08;JavaServer Pages&#xff09;是一种用于创建动态网页的技术&#xff0c;它允许在HTML页面中嵌入Java代码&#xff0c;从而实现动态内容的生成。JSP与Servlet一样&#xff0c;都是Java EE平台的一部分&am…

随机森林的知识博客:原理与应用

随机森林&#xff08;Random Forest&#xff09;是一种基于决策树的集成学习算法&#xff0c;它通过组合多棵决策树的预测结果来提升模型的准确性和稳健性。随机森林具有强大的分类和回归能力&#xff0c;广泛应用于各种机器学习任务。本文将详细介绍随机森林的原理、构建方法及…

大数据系列之:Java8和java11查看进程堆内存使用情况

大数据系列之:Java8和java11查看进程堆内存使用情况 Java8查看进程堆内存java11查看进程堆内存进程堆内存使用情况评估Java8查看进程堆内存 jmap -F -heap 2723jmap -F -heap 2723是一个Java命令行工具jmap的使用示例。它用于生成Java进程2723的堆内存信息。其中,-F选项表示…

JavaSE-易错题集-001

1. AccessViolationException异常触发后&#xff0c;下列程序的输出结果为&#xff08; &#xff09; 1 2 3 4 5 6 7 8 9 10 11 12 13 static void Main(string[] args) { try { throw new AccessViolationException(); Console.Write…

OpenCV图像分割教程

OpenCV 图像分割教程 OpenCV 是一个非常强大的计算机视觉库&#xff0c;支持各种图像处理任务。图像分割是 OpenCV 支持的一个重要功能&#xff0c;它用于将图像划分为不同的区域&#xff0c;识别感兴趣的部分。我们将通过介绍 OpenCV 中的图像分割方法&#xff0c;包括基础功…

ubantu安装mysql + redis数据库并使用C/C++操作数据库

mysql 安装mysql ubuntu 安装 MySql_ubuntu安装mysql-CSDN博客 Ubuntu 安装 MySQL 密码设置_ubuntu安装mysql后设置密码-CSDN博客 service mysql restart1 C/C连接数据库 C/C 连接访问 MySQL数据库_c mysql-CSDN博客 ubuntu安装mysql的c开发环境_ubuntu 搭建mysql c开发…

测试一些概念

软件测试 软件测试流程 需求分析&#xff1a;在这个阶段&#xff0c;测试人员会审查和分析项目的需求文档&#xff0c;以确保他们理解需要测试的功能和特性。 制定测试计划&#xff1a;在这个阶段&#xff0c;测试人员会制定一个详细的测试计划&#xff0c;包括测试目标、测…

跨越技术壁垒:EasyCVR为何选择支持FMP4格式,重塑视频汇聚平台标准

随着物联网、大数据、云计算等技术的飞速发展&#xff0c;视频监控系统已经从传统的安防监控扩展到智慧城市、智能交通、工业制造等多个领域。视频流格式作为视频数据传输与存储的基础&#xff0c;其兼容性与效率直接影响到整个视频监控系统的性能。 在众多视频流格式中&#…

TCP Analysis Flags 之 TCP Port numbers reused

前言 默认情况下&#xff0c;Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态&#xff0c;并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时&#xff0c;会对每个 TCP 数据包进行一次分析&#xff0c;数据包按照它们在数据包列表中出现的顺序进行处理。可…