复杂度分析复习(C语言版)

一.算法复杂度

算法在编写成可执行程序以后,运行时需要耗费时间资源和(内存)资源。因此衡量一个算法的好坏,一般是从时间、空间两个维度来衡量的,即时间复杂度和空间复杂度。

现如今,计算机内存越来越大,所以空间复杂度已经不是最主要的考量标准了;现在会比较注重时间复杂度的考量。

二.时间复杂度

时间复杂度定义:算法的时间复杂度是一个函数(此函数非彼函数),它定量描述了该算法的运行时间。一个算法所花费的时间与其中语句的执行次数形成正比例,算法中的基本操作的执行次数,为算法的时间复杂度

即找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度

1.基础时间复杂度 

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--){++count;}
}

 基本语句与问题规模N之间的数学表达式可以抽象地看成,循环语句共执行了多少次,在最开头的部分,循环语句出现嵌套,被嵌套的循环语句每循环N次,外面的语句循环1次,因此共循环N^2次.接下来的循环语句共循环2*N次,以及共循环10次.所以函数表达式应该为 N^2 + 2*N + 10

 请判断下面三种情况下的时间复杂度分别应该是多少?

1. F(N) = N^2 + 2*N +10

2. F(N) = N + 100

3. F(N) = N^3 + N


在时间复杂度计算时,我们一般只会使用到渐近表示法,即O(N)。即只判断算法属于哪个量级。

就拿情况1来举例

N = 10   F(N) = 130   N^2 = 100

N = 100 F(N) = 10210  N^2 = 10000

N = 1000 F(N) = 1002010 N^2 = 1000000     

通过上述例子,我们不难发现 N^2 对整个函数表达式影响是最大的,因此当我们在使用渐近表示法时,只保留对整个函数式影响最大的那项(或许会有读者疑惑:那N = 10时,其他项对函数表达式影响也非常大,可为什么就只考虑N很大的情况呢?这是因为现如今的CPU都太过强大,一秒可以执行上亿条语句;因此执行的代码量很小的情况下,可以近似为是相等的时间复杂度,因此不去考虑N很小的情况),即只保留N^2因此情况1最后结果为O(N^2)。同理可得,情况2结果为O(N),情况3结果为O(N^3).


请判断下述情况的时间复杂度

F(N) = 2*N + 10


上述情况下,无论N的系数大小为多少,我们都会把N的系数去除.

我们可以假设一种情况,即有个富翁a身价1000亿,有个富翁b身价2000亿,他们两个虽然在身价上相差两倍,但是豪宅和跑车对于他们来说同样便宜.因此我们完全可以把N前的系数忽略不计

因此上述情况,结果为O(N)


请判断下述两种情况的时间复杂度

1.O(M+N),M远大于N

2.O(M+N),N远大于M


上述情况下,如果M大那就保留M;如果N大就保留N.

因此,最后的结果为情况1是O(M),情况2是O(N)


请判断下述情况的时间复杂度

F(N) = 100


最后结果为O(1),此处的O(1)代表的不是1次,而是常数次

const char * strchr ( const char * str, int character )
{while(*str){if(str == character){return str;}else++str;}

上述代码中,最好的情况为O(1),最坏的情况为O(n)。根据大O渐进表示法,保留最差的情况,因此结果为O(n)。

void func(int n)
{int x=0;for(int i=1;i<n;i*=2){x++;}
}

假设循环了x次,那么1×2×2×2×2×……×2=n。因此 2^x = n,x = \log_{2}n。在计算机中,由于\log_{2}n比较难表示出来,因此一般性会把\log_{2}n表示成logN。所以上述代码的时间复杂度为O(logN)。 

 2.clock函数介绍

int main()
{int begin1 = clock(); //语句1int n = 100000000;int x = 10;for (int i = 0; i < n; ++i){++x;}int end1 = clock(); //语句2printf("%d ms\n", end1-begin1);return 0;
}

在上文中,笔者已经提到:问题规模的大小会影响时间复杂度。而C语言自带的clock函数就是为了搞清楚代码语句之间的用时(例如上述代码,clock函数用来计算从语句1到语句2所花费的时间)。打印出来的结果如下所示

 c1a072c0f02b47ad886204e609a36c6c.jpg

3.时间复杂度总结

大O符号:是用于描述函数渐近行为的数学符号。(本质:计算时间复杂度属于哪个量级)

推导大O阶方法:

  1. 用常数1取代运行时间中所有的加法常数
  2. 在修改后的运行次数函数中,只保留最高阶数
  3. 如果最高阶数存在且不是1,则去除这个项目相乘的常数。得到的结果即为大O阶。

b0bd2861287147ec95360ede920e70f0.jpg

4.常见算法的时间复杂度

  • 冒泡排序
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;}
}

前后两者 一 一依次 比较,第一次遍历比较能确定1个数字的位置,第二次遍历(此时有一个数字可以不参加比较)比较能确定2个数字的位置……;因此时间复杂度为 N-1(第一次比较)+N-2(第二次比较)+N-3+……+2+1,结果即为 (N(N-1))/2。根据大O比较法,结果为O(N^2)。

  • 二分查找
int BinarySearch(int* a, int n, int x) {assert(a);int begin = 0;int end = n-1;// [begin, end]: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 n/2 n/4 …… 4 2 1 这样的一个规律

因此,在最坏情况下(查找区间只剩一个数,或者没找到),n/2/2/……/2 = 1 。查找了x次,就除了x次2。因此2^x = n,最后时间复杂度为 log N 。

二分查找的缺点:a.需要排序    b.不便于插入删除

  •  递归阶乘实现
long long Fac(size_t N) {if(0 == N)return 1;return Fac(N-1)*N; }

递归相当于多个函数调用的累加和

阶乘函数是Fac(N) Fac(N-1) Fac(N-2) …… Fac(2) Fac(1) Fac(0)

因此总共调用了 N+1 次Fac函数,最后时间复杂度应为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; }

如下图所示,第一函数调用中,共循环了N次;第二次循环函数调用中,循环了N-1次。构成了等差数列,最后结果为 (N(N+1))/2 。因此时间复杂度为O(N^2) 。

 

 

  • 斐波那契数列求和递归实现
long long Fib(size_t N) {if(N < 3)return 1;return Fib(N-1) + Fib(N-2);
}

在探讨该问题前,需要先明白:递归时间复杂度是所有递归调用次数求和

如下图所示,第一层中,函数调用了 Fib(N-1) 和 Fib(N-2);第二层中,Fib(N-1) 和 Fib(N-2) 分别调用了2次函数,总共调用了4次;由此可得,最后一次调用,总共调用了2^(N-2)。

每层调用次数之间构成了公比为2的等比数列,总层数可以通过最左边的一条结点链条(即 Fib(N-1) -> Fib(N-2) -> …… -> Fib(3) -> Fib(2))得出。即有 2^(N-1) 层,那么最后一层调用了 2^(N-2) 次。

构成了等比数列,最后求和结果为 2^(N-1)-1 。因此时间复杂度为O(2^N),非常惊人的高,所以一般不推荐使用递归来实现斐波那契数列求和。(总不能放进去一个100,告诉用户数字太大了换个小点的吧doge)

 

注意:这边的最后一层的2^(n-2)次运算是估算,实际上并没有进行那么多次。这是因为最左边的那一连串结点每次是 -1,最右边那一连串结点每次是 -2 。因此可以发现,最后的调用次数图右小角那块会是缺失的,就像下图一样。(灰色代表空)

 三.空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中 临时占用存储空间大小的量度
空间复杂度不是程序占用了多少 bytes 的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。
空间复杂度计算规则基本跟实践复杂度类似,也使用 O 渐进表示法
注意: 函数运行时所需要的栈空间 ( 存储参数、局部变量、一些寄存器信息等 ) 在编译期间已经确定好了,因 此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
总结:空间复杂度为解决某个问题时,额外开辟的空间。
(常见的空间复杂度只有 O(1) 、O(N) 和 O(N^2) )

 常见算法的空间复杂度:

  • 冒泡排序

没有新开辟任何的数组,因此为O(1)

  •  递归阶乘实现

每次函数调用都需要建立栈帧,总共会开辟n个栈帧,因此空间复杂度为O(N)

  • 斐波那契数列求和递归实现

总共开辟了N个函数栈帧,因此空间复杂度为O(N)

  • 斐波那契数列求和数组实现
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; }

开辟了一个新数组,因此空间复杂度为O(N)

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数学公式编辑器免费版下载,mathtype和latex哪个好用

选择适合自己的公式编辑器需要考虑多个因素。首先&#xff0c;您需要确定编辑器支持的功能和格式是否符合您的需求&#xff0c;例如是否可以插入图片、导出各种文件格式等。其次&#xff0c;您可以考虑编辑器的易用性和界面设计是否符合您的个人喜好。另外&#xff0c;您还可以…

基于LORA的一主多从监测系统_框架搭建

第一节、框架搭建 打开CubeMAX&#xff0c;选择好芯片&#xff0c;进行基础配置 第一步、先配置时钟源 第二步、配置SYS选项 配置debug口以及计数器源&#xff0c;我这里选择TIM1 第三步、选择I2C接口 配置如下即可&#xff0c;默认配置不用改 第四步、串口选择 我们这里使…

传奇服务端快捷助手

定位传奇各目录&#xff0c;一键打开各配置文件。<br>收纳引擎、端口配置检查&#xff08;批量&#xff09;、路径配置、文本搜索、文件同步、一键重载&#xff08;跨桌面&#xff09;、命令管理 参考资料 传奇服务端快捷助手2024-06-20 - 工具软件程序 - 51开发者联盟 -…

51单片机的自动制冷系统【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块温度传感器继电器LED、按键和蜂鸣器等模块构成。适用于车载便携式自动制冷系统、冰箱制冷、温度控制等相似项目。 可实现功能: 1、LCD1602实时显示当前温度 2、温度传感器DS18B20采集温度 3、按键可设置温度的阈…

JS 入门

文章目录 JS 入门一、JS 概述1、JS 特点2、JS 组成3、JS 初体验4、HTML引入JS 二、JS 基础语法1、变量声明2、基本数据类型3、引用数据类型1&#xff09;数组2&#xff09;对象3&#xff09;函数4&#xff09;null 4、运算符5、条件判断6、循环语句 三、JS 函数0、JS 函数特点1…

【unity进阶知识9】序列化字典,场景,vector,color,Quaternion

文章目录 前言一、可序列化字典类普通字典简单的使用可序列化字典简单的使用 二、序列化场景三、序列化vector四、序列化color五、序列化旋转Quaternion完结 前言 自定义序列化的主要原因&#xff1a; 可读性&#xff1a;使数据结构更清晰&#xff0c;便于理解和维护。优化 I…

字符编码发展史5 — UTF-16和UTF-32

上一篇《字符编码发展史4 — Unicode与UTF-8》我们讲解了Unicode字符集与UTF-8编码。本篇我们将继续讲解字符编码的第三个发展阶段中的UTF-16和UTF-32。 2.3. 第三个阶段 国际化 2.3.2. Unicode的编码方式 2.3.2.2. UTF-16 UTF-16也是一种变长编码&#xff0c;对于一个Unic…

第Y2周:训练自己的数据集

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 在上一次体验yolov5s的为基础上&#xff0c;这次将训练自己的数据集。 在YOLO目标检测算法中常用的三种标签格式&#xff1a;voc(xml)、coco(json)和yolo(txt…

【多线程】详解 CAS 机制

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. CAS 是什么1.1 CAS 具体步骤1.2 CAS 伪代码 2. CAS 的应用2.1 实现原子类2.1.1 AtomInteger 类2.1.2 伪代…

Rspamd:开源垃圾邮件过滤系统

Rspamd 是一个开源垃圾邮件过滤和电子邮件处理框架&#xff0c;旨在根据各种规则评估消息&#xff0c;包括正则表达式、统计分析以及与 URL 黑名单等自定义服务的集成。 系统会分析每封邮件并做出判定&#xff0c;MTA可据此采取进一步行动&#xff0c;例如拒绝邮件或添加垃圾邮…

低照度图像增强网络——EnlightenGAN

系列文章目录 GAN生成对抗网络介绍https://blog.csdn.net/m0_58941767/article/details/142704354?spm1001.2014.3001.5501 循环生成对抗网络——CycleGANhttps://blog.csdn.net/m0_58941767/article/details/142704671?spm1001.2014.3001.5501 目录 系列文章目录 前言 …

SSM社区慢性病管理系统—计算机毕业设计源码37572

摘 要 社区慢性病管理是社区卫生服务的主要内容&#xff0c;发展社区卫生服务是提供基本卫生服务、满足人民群众日益增长的卫生服务需求&#xff0c;也是提高人民健康水平的重要保障。为迎接慢性病防治的挑战我国进行了社区卫生服务改革&#xff0c;但由于社区卫生存在的诸多问…

OJ在线评测系统 微服务 OpenFeign调整后端下 nacos注册中心配置 不给前端调用的代码 全局引入负载均衡器

OpenFeign内部调用二 4.修改各业务服务的调用代码为feignClient 开启nacos注册 把Client变成bean 该服务仅内部调用&#xff0c;不是给前端的 将某个服务标记为“内部调用”的目的主要有以下几个方面&#xff1a; 安全性: 内部API通常不对外部用户公开&#xff0c;这样可以防止…

【CF2021E】Digital Village(All Version)

题目 给你一张 n n n 个点 m m m 条边的无向图&#xff0c;有 p p p 个关键点。你需要选择 k k k 个点染黑&#xff0c;使得这 p p p 个关键点到这 k k k 个黑点的代价和最小。定义代价为两点之间边权最大的边的最小值。 你需要求出 k 1,2,…,n 的所有答案 E1 n,m,p&l…

fiddler抓包20_弱网模拟

课程大纲 ① 打开CustomRules.js文件&#xff1a;Fiddler快捷键“CtrlR”(或鼠标点击&#xff0c;菜单栏 - Rules - Customize Rules)。 ② 设置速率&#xff1a;“CtrlF”&#xff0c;搜索 “m_SimulateModem”&#xff0c;定位至函数。在函数里设置上传、下载速率&#xff0c…

乔斯编程——P3283 通信救援

说明 众所周知&#xff0c;在同一平面内到定点的距离等于定长的点的集合叫做圆。这个定点叫做圆的圆心&#xff0c;定长即圆的半径。 同时用圆心的坐标和圆的半径&#xff0c;就可以确定圆在平面内的位置&#xff0c; 在本题当中&#xff0c;我们根据圆在平面覆盖的区域来描述…

全面解析大型模型Agent智能体原理及实践案例

1 什么是大模型 Agent &#xff1f; 大模型 Agent&#xff0c;作为一种人工智能体&#xff0c;是具备环境感知能力、自主理解、决策制定及执行行动能力的智能实体。简而言之&#xff0c;它是构建于大模型之上的计算机程序&#xff0c;能够模拟独立思考过程&#xff0c;灵活调…

动态规划10:174. 地下城游戏

动态规划解题步骤&#xff1a; 1.确定状态表示&#xff1a;dp[i]是什么 2.确定状态转移方程&#xff1a;dp[i]等于什么 3.初始化&#xff1a;确保状态转移方程不越界 4.确定填表顺序&#xff1a;根据状态转移方程即可确定填表顺序 5.确定返回值 题目链接&#xff1a;174.…

【FPGA】面试八股

1.FPGA的底层资源有哪些 &#xff08;1&#xff09;可编程的逻辑资源 可编程的逻辑单元由查找表&#xff08;LUT&#xff09;,数据选择器&#xff08;MUX&#xff09;,进位链&#xff08;Carry Chain&#xff09;和触发器&#xff08;Flip-Flop&#xff09; &#xff08;2&…

毕业设计——物联网设备管理系统后台原型设计

作品详情 主要功能&#xff1a; 通过构建数字化综合体&#xff0c;利用物联网技术、设备监控技术采集生产线设备等物对象的实时数据&#xff0c;加强信息汇聚管理和服务&#xff0c;多系统维度、多层次的清楚地掌握设施各系统的状态&#xff0c;提高厂房服务的可控性、安全性&…