数据结构·复杂度

目录

1 时间复杂度

2 大O渐进表示法

举例子(计算时间复杂度为多少)

3 空间复杂度


前言:复杂度分为时间复杂度和空间复杂度,两者是不同维度的,所以比较不会放在一起比较,但是时间复杂度和空间复杂度是用来衡量一个算法是否好坏的标准,时间复杂度用来描述算法运行的时间快慢,空间复杂度用来衡量一个算法所需要的额外空间。最初的计算机时代计算机的存储量很小,所以额外注重空间复杂度,随着发展,计算机的存储已经不是让人担心的点了,所以更为注重时间复杂度。


1 时间复杂度

时间复杂度的定义上可以认为使劲按复杂度是一个函数,定量的描述了算法所需要的时间,但是理论上来说,运行的时间是要上机测试才能测试出来的,实际测试就会花很多时间,所以有了时间复杂度这个分析方式分析算法中执行的基本操作的次数,认定为时间复杂度。

int main()
{for (int i = 0; i < N; i++){for (int j = 0; j < N; j++){//测试语句}}for (int i = 0; i < N; i++){//测试语句}int M = 10;while (M--){//测试语句}return 0;
}

这段代码的时间复杂度是?

两个嵌套的for循环,也就是执行了N^2次,再来一个for循环,执行次数为N,最后while收尾,执行次数为10,所以时间复杂度的函数为F(N) = N^2 + N + 10,随着N的增大,式子的值会大到无法想象 ,这都得益于N^2,那么整个式子的决定性因素是N^2,所以我们就认为时间复杂度是N^2。

这种估算的方法被称为大O渐进表示法,只取式子中的决定性因素。


2 大O渐进表示法

计算时间复杂度的时候我们通常采用大O渐进表示法,推导大O阶的表示方法为:

1、用常数1取代运行时间中的所有加法常数。

2、在修改后的运行次数函数中,只保留最高阶项。

3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

这里其实完全可以类比高中的数学函数,y = x,x可以是2x也可以是3x,这就是为什么舍弃常数的原因,x和2x是没有区别的。

那么什么是加法常数呢?只要没有循环或者递归,我们都可以认为执行次数为O(1),哪怕是写了一万行代码。

执行程序的时候会存在最好情况 最坏情况 以及平均情况(期望值),一般计算时间复杂度的时候都是计算的最坏情况,所以像冒泡排序,运气好点,时间复杂度就是O(1),运气不好就是O(N^2)了。

举例子(计算时间复杂度为多少)

void Func2(int N)
{int count = 0;for (int k = 0; k < 2 * N; k++){count++;}int M = 10;while (M--){count++;}printf("%d ", count);
}

第一个for循环的执行次数为2 * N次,第二个while循环执行次数为10次,那么函数表达式就是2*N + 10,根据大O表示法,时间复杂度为O(N)。

void Fun3(int N, int M)
{int count = 0;for (int k = 0; k < M; k++){count++;}for (int k = 0; k < N; k++){count++;}printf("%d ", count);
}

第一个for循环执行次数为M次,第二个for循环的执行次数为N次,那么函数表达式就是O(M + N),

那么最后结果视结果而定,如果M远大于N,那么时间复杂度就是O(M),那么N >> M同理可得。

void Func4(int N)
{int count = 0;for (int k = 0; k < 100; k++){count++;}printf("%d", count);
}

根据第一个for循环的循环条件,循环次数为100次,是常数,所以时间复杂度就是O(1)。

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

冒泡排序严格意义上来说不是标准的O(N^2),因为它的执行次数在随着程序的执行是逐渐减少的,最开始两两比较的次数是N- 1,每趟下来,就会确定一个数据的位置,所以两两比较的次数每次都会减去1,那么if这个语句执行的次数就是N - 1 N - 2……1,利用高中的等差数列的知识,可以得到时间复杂度的函数是F(N) = (N - 1) * (N - 1 + 1) / 2,根据大O表示法,可得得出复杂度为O(N^2)。

int BinarySeatch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n - 1;//[begin,end]是查找区间while (begin <= end){int mid = begin + ((end - begin) >> 1);if (a[mid] < x)begin = mid + 1;else if (a[mid] > x)end = mid - 1;elsereturn mid;}return -1;
}

这是一个典型的二分查,时间复杂度为直接看是看不出来的,所以有的代码计算时间复杂度是要结合画图的:

我们讨论最坏情况,二分查找的本质就是不断的缩小区间,一半一半的缩短,那么最开始有N个值,就有N/2/2/2/2/2/2……=  1,那么执行次数就是找的次数就是除以2的次数,计算方式就是

N = 2^x,x是执行的次数,我们求的就是x的值,那么利用高中的换底公式,我们可以得到

x是以2为底,N的对数,而因为对数不太好写,除非使用专业的公式编辑器,所以默认规定LogN,表示的就是以2为底,N的对数,如果有其他底数,就照常写。

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

计算阶乘递归的时间复杂度,递归,会多次开辟函数栈帧,所以一次递归,就会开辟一个函数栈帧,执行次数是1,那么递归n次,总执行次数就是N,所以时间复杂度就是O(N)。

引申:

long long Fac(size_t N)
{if (0 == N)return 1;for (int i = 0; i < N; i++){//测试语句}return Fac(N - 1) * N;
}

 递归函数里面加了一个for循环,时间复杂度是多少呢?

不加for循环之前,每个函数的时间复杂度是O(1),开辟了N个函数,那么复杂度就是O(N),但是现在每个函数的时间复杂度就是O(N)了,因为每个子函数里面都有一个for循环,所以N个O(N)的函数放在一起,时间复杂度就是O(N ^ 2)。

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

我们知道递归用来计算斐波那契数列是非常不划算的,因为重复计算的次数太多了,是次方级别的重复:

像这样,函数执行的次数是从2的0次方开始,一直到2的N次方,那么利用高中的等比数列的公式,可以得出时间复杂度为函数为F(N) = 2^N - 1,所以时间复杂度就是O(2 ^ N)。

这是非常恐怖的,所以计算斐波那契数列的话还是使用迭代吧!


3 空间复杂度

时间复杂度可以理解为语句的执行次数,空间复杂度可以理解额外开辟的空间,也是采用的大O渐进表示法。当然,空间复杂度不是多少字节,意义不大,因为当前的计算机存储足够大,所以空间复杂度表示的是变量的个数,需要注意的是:函数需要的栈空间在编译期间就已经确定好了,所以计算空间复杂度靠的是程序运行时候显示出来的额外空间。

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

计算冒泡排序的空间复杂度:

 这个函数里面有变量,但是是有限个的,如end flag i ,并没有额外开辟空间,所以空间复杂度是O(1),毕竟是没有额外申请空间的。

那么递归计算斐波那契数列的空间复杂度是多少呢?

在此之前我们先看这串代码:

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

试问运行结果是不是一样的?有人就会问了,不同函数存的地址肯定不是一样的啊,一般情况是这样的,但是如果两个函数连续调用,并且函数的功能一样,对空间的需求是一样的,那么内存在栈上的空间分配就不会额外开辟空间,也就是说一个函数调用完后,另一个函数就会接着使用这块空间,所以地址是一样的。

那么类比到斐波那契数列的重复计算里面:

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

实际上上开辟的空间都是为了计算函数Fib(N)到Fib(1)的,函数的功能是一样,对空间的需求也是一样的,所以重复计算的时候就不会单独开辟空间,所以需要计算的,都用了开辟的Fib(N)到Fib(1)的空间,那么空间复杂度就是O(N)。


感谢阅读!

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

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

相关文章

汉服|高校汉服租赁网站|基于Springboot的高校汉服租赁网站设计与实现(源码+数据库+文档)

高校汉服租赁网站目录 目录 基于Springboot的高校汉服租赁网站设计与实现 一、前言 二、系统设计 三、系统功能设计 1、汉服信息管理 2、汉服租赁管理 3、公告管理 4、公告类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选…

22.1 线程安全及性能:ThreadLocal(❤❤)

22.1 分布式_ThreadLocal 1. 简介1.1 使用场景2. ThreadLocal实现线程独享对象2.1 基于SimpleDateFormat讲解ThreadLocal优势1. 2个线程分别使用SimpleDateFormat对象2. 10个线程甚至更多使用SimpleDateFormat对象3. 基于线程池使用SimpleDateFormat对象4. 优化SimpleDateForma…

GPT实战系列-构建多参数的自定义LangChain工具

GPT实战系列-构建多参数的自定义LangChain工具 LangChain系列 GPT实战系列-LangChain如何构建基通义千问的多工具链 GPT实战系列-构建多参数的自定义LangChain工具 GPT实战系列-通过Basetool构建自定义LangChain工具方法 GPT实战系列-一种构建LangChain自定义Tool工具的简…

SQL Server错误:15404

执行维护计划失败&#xff0c;提示SQL Server Error 15404 无法获取有关... 异常如下图&#xff1a; 原因&#xff1a;数据库用户名与计算机名称不一致 解决办法&#xff1a;1.重名称数据库用户名 将前缀改成计算机名 2.重启SQL Server代理

【数据挖掘】实验1:R入门(内含详细R和RStudio安装教程)

实验1&#xff1a;R入门 一&#xff1a;实验目的与要求 1&#xff1a;根据上课PPT内容&#xff0c;掌握课堂知识并进行代码练习操作&#xff0c;提供练习过程和结果。 2&#xff1a;可COPY代码运行结果直接提交&#xff0c;如涉及到输出图等可截图。 二&#xff1a;实验内容 …

免费搭建导航网站教程带免费空间域名源码

使用免费空间和免费域名免费搭建一个导航网站 手把手视频教程 https://pan.xunlei.com/s/VNsoMehs7RCjz3IClV6h2vNMA1?pwdq596#

中国首个基于区块链的分布式算力网络上线

随着美国人工智能公司OpenAI近期发布的Sora视频模型&#xff0c;全球对高性能算力的需求突破了历史新高。Sora的创新在于它能够以超长生成时间、多角度镜头捕捉&#xff0c;理解物理世界的能力&#xff0c;这不仅是技术的一大突破&#xff0c;更是对算力需求的一大挑战。在这样…

使用npm版本管理工具解决npm 的EACCES permissions errors when installing packages globally错误

EACCES错误通常表示“权限被拒绝”&#xff0c;意味着您没有足够的权限来执行某个操作。在计算机领域&#xff0c;尤其是在文件系统和程序安装中&#xff0c;这个错误很常见。以下是可能导致EACCES错误的原因以及相应的解决方法&#xff1a; 文件系统权限&#xff1a;当您尝试…

【开源】SpringBoot框架开发智慧社区业务综合平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 业务类型模块2.2 基础业务模块2.3 预约业务模块2.4 反馈管理模块2.5 社区新闻模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 业务类型表3.2.2 基础业务表3.2.3 预约业务表3.2.4 反馈表3.2.5 社区新闻表 四、系统展…

【机器学习300问】34、决策树对于数值型特征如果确定阈值?

还是用之前的猫狗二分类任务举例&#xff08;这个例子出现在【机器学习300问】第33问中&#xff09;&#xff0c;我们新增一个数值型特征&#xff08;体重&#xff09;&#xff0c;下表是数据集的详情。如果想了解更多决策树的知识可以看看我之前的两篇文章&#xff1a; 【机器…

按键+串口发送实验

摸鱼记录 Day_15 &#xff5e;(&#xffe3;▽&#xffe3;&#xff5e;)(&#xff5e;&#xffe3;▽&#xffe3;)&#xff5e; review 前边已经学习了&#xff1a; 串口发送Vivado 串口通信(UART)------串口发送-CSDN博客 按键基于状态机的按键消抖实现-CSDN博客 1. …

STM32外设分类--学习笔记

简介: 本文在于根据自己的理解&#xff0c;将stm32f103外设按照功能分个类别&#xff0c;便于记忆。下面的几张图一定要熟悉&#xff0c;后期编写代码时能够快速找到想要的功能和对应的引脚。 我使用的工具链是&#xff1a;使用CubeMX完成keil5工程搭建和引脚初始化功能,然后用…

Grafana

介绍 官网&#xff1a;https://grafana.com/ Grafana 是一个开源的指标分析和可视化工具&#xff0c;它被广泛用于展示和监控云基础设施和应用程序的实时数据。Grafana 提供了一个强大且易于使用的界面&#xff0c;允许用户创建各种图表、图形和仪表盘&#xff0c;以直观地展…

探索HDFS读写流程、节点机制和数据完整性

目录 写在前面一、HDFS的读写流程1.1 HDFS写数据流程1.2 机架感知1.3 HDFS读数据流程1.4 小结 二、 NameNode和SecondaryNameNode2.1 NN和2NN工作机制2.2 Fsimage和Edits解析2.2.1 oiv查看Fsimage文件2.2.2 oev查看Edits文件 2.3 CheckPoint时间设置 三、DataNode3.1 DataNode工…

案例分析篇14:信息系统安全设计考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…

Unity URP 如何写基础的几何着色器

这是使用几何着色器在点中心生成一个点并根据这个点把原本的面片分成三个三角形的操作。 对于几何着色器构造相对简单&#xff0c;网上的信息也相对较多&#xff0c;需要注意的点就是需要提供一个新的数据结构供几何着色器输出&#xff0c;因为几何着色器在顶点之后&#xff0…

哈达玛矩阵与克罗内克积

哈达玛矩阵与克罗内克积在计算机视觉中发挥着重要作用,例如哈希感知等场景下都可能用到这两个知识点。 例如: 论文:Visually meaningful image encryption scheme based on new-designed chaotic map and random scrambling diffusion strategy 中有一句: “Construct a Ha…

UVC 设备框架在 Linux 4.15 内核的演变

1. 概述 发现之前的uvc框架和现在的还是有一些差别的&#xff08;比如从videobuf 过渡到videobuf2&#xff09;&#xff0c;写个blog记录一下&#xff0c;方便以后查询&#xff0c;我的内核版本&#xff1a;Linux 4.15 UVC&#xff08;USB Video Class&#xff09;设备框架是…

探秘Nutch:揭秘开源搜索引擎的工作原理与无限应用可能(三)

本系列文章简介&#xff1a; 本系列文章将带领大家深入探索Nutch的世界&#xff0c;从其基本概念和架构开始&#xff0c;逐步深入到爬虫、索引和查询等关键环节。通过了解Nutch的工作原理&#xff0c;大家将能够更好地理解搜索引擎背后的原理&#xff0c;并有能力利用Nutch构建…

Idea、VsCode、WebStorm常用插件

持续更新&#xff0c;见&#xff1a;工具库/Idea、VsCode、WebStorm常用插件.md 1. Idea 常用插件 MybatisX&#xff1a;mybatis选手必备&#xff0c;一键跳转&#xff0c;自动生成&#xff0c;节省开发效率。&#xff08;Java玩家必备&#xff09; GitToolBox&#xff1a;gi…