算法的时间复杂度与空间复杂度

       俗话说“条条大路通罗马”, 我们在用算法解决某一个问题时,往往会存在多种解决方法,但正如道路有远近之分,不同的算法也应该是有优劣的。为了更加清晰的量化算法的优劣,我们就需要引入算法的时间复杂度与空间复杂度了。那么就由小编来带大家梳理一下吧

一、时间复杂度

 

1、时间复杂度的概念

         时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个数学函数 ,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,
算法中的基本操作的执行次数,为算法的时间复杂度。

2、时间复杂度的求法

1、O(n)渐进表示法

让我们来看一下下列代码:

// 请计算一下func1基本操作执行了多少次?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--) > 0) {count++;}System.out.println(count);}

        第一段有一个双重for循环,全部遍历完需要N^2次,中间的单层for循环遍历完需要N次,最后的while循环由于M的值是10,因此遍历完需要10次。

所以func1的基本操作执行的总次数就为:

F(N)=N^2+N+10

这时我们试着带入几种情况试一试:

  • N = 10      F(10) = 130
  • N = 100    F(100) = 10210
  • N = 1000  F(1000) = 1002010

我们会发现随着N取值的增大,F(N)的决定项中N和10对总次数的影响会越来越小,运用数学中的极限的思想,当N非常大时,F(N)的取值将只由项N^2决定,这时我们就可以说func1的时间复杂度为O(N^2)了。

实际中我们计算时间复杂度时,其实并不一定要计算精确的执行次数,而只需要 大概执行次数,那么这里我们就 使用大 O 的渐进表示法。
O符号(Big O notation :是用于描述函数渐进行为的数学符号。

2、推导大O阶方法

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

上面我们在推导时其实就是对这些原理的具体阐释,Func1的时间复杂度为:O(N^2)

这时我们再带入几个值看看:

  • N = 10 F(N) = 100
  • N = 100 F(N) = 10000
  • N = 1000 F(N) = 1000000
正如我们之前的推导,通过上面我们会发现大 O 的渐进表示法 去掉了那些对结果影响不大的项 ,简洁明了的表示出了执行次数。
注意:
有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数 ( 上界 )
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数 ( 下界 )
例如:在一个长度为 N 数组中搜索一个数据 x
最好情况: 1 次找到
最坏情况: N 次找到
平均情况: N/2 次找到
在计算时间复杂度时,我们一般都是考虑最坏情况
其实仔细想想, 在应用总对运行时间有严格要求时,如果最坏情况都符合要求的话,那这算法不就一定符合要求了嘛

3、常见的时间复杂度计算举例

1、非递归

(1)

// 计算func2的时间复杂度?
void func2(int N) {
int count = 0;
for (int k = 0; k < 2 * N ; k++) {
count++;
}
int M = 10;
while ((M--) > 0) {
count++;
}
System.out.println(count);
}
基本操作执行了 2N+10 次,通过推导大 O 阶方法知道,时间复杂度为 O(N)

(2)

// 计算func3的时间复杂度?
void func3(int N, int M) {
int count = 0;
for (int k = 0; k < M; k++) {
count++;
}
for (int k = 0; k < N ; k++) {
count++;
}
System.out.println(count);
}
基本操作执行了 M+N 次,有两个未知数 M N ,时间复杂度为 O(N+M)

(3)

// 计算func3的时间复杂度?void func3(int N) {int count = 0;for (int k = 0; k < 100; k++) {count++;}System.out.println(count);}
基本操作执行了 100 次,通过推导大 O 阶方法,时间复杂度为 O(1)

(4)

// 计算bubbleSort的时间复杂度?void bubbleSort(int[] array) {for (int end = array.length; end > 0; end--) {boolean sorted = true;for (int i = 1; i < end; i++) {if (array[i - 1] > array[i]) {Swap(array, i - 1, i);sorted = false;}}if (sorted == true) {break;}}}
基本操作执行最好 N
最坏执行了 (N*(N-1))/2
通过推导大 O阶方法 + 时间复杂度一般看最坏
时间 复杂度为 O(N^2)

(5)

// 计算binarySearch的时间复杂度?int binarySearch(int[] array, int value) {int begin = 0;int end = array.length - 1;while (begin <= end) {int mid = begin + ((end-begin) / 2);if (array[mid] < value)begin = mid + 1;else if (array[mid] > value)end = mid - 1;elsereturn mid;}return -1;}
基本操作执行最好 1次
最坏log2N次
时间复杂度为 O( log2N)
ps: log2N 在算法分析中表示是底数 2 ,对数为 N, 有些地方会写成 lgN。
( 建议通过折纸查找的方式讲解 logN 是怎么计算出来的)
( 因为二分查找每次排除掉一半的不适合值, 一次二分剩下: n/2 两次二分剩下:n/2/2 = n/4)

究其根本,求解时间复杂度就是在求最坏情况下程序执行的次数

2、递归

其实递归类型看着复杂,其核心求法就是:

时间复杂度=递归次数*每次递归的执行次数

(6)

// 计算阶乘递归factorial的时间复杂度?long factorial(int N) {return N < 2 ? N : factorial(N-1) * N;}
通过计算分析发现基本操作递归了 N 次,每次递归执行1次,时间复杂度为 O(N)

(7)

// 计算斐波那契递归fibonacci的时间复杂度?int fibonacci(int N) {return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);}
通过计算分析发现基本操作递归了2^N次,每次递归执行1次,时间复杂度为O(2^N)

二、空间复杂度

         在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度,所以这里我们就简单介绍一下
空间复杂度是对一个算法在运行过程中 临时占用存储空间大小的量度
空间复杂度不是程序占用了多少 bytes 的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。
空间复杂度计算规则基本跟时间复杂度类似,也使用 O 渐进表示法
例1
// 计算bubbleSort的空间复杂度?void bubbleSort(int[] array) {for (int end = array.length; end > 0; end--) {boolean sorted = true;for (int i = 1; i < end; i++) {if (array[i - 1] > array[i]) {Swap(array, i - 1, i);sorted = false;}}if (sorted == true) {break;}}}
使用了常数个额外空间,所以空间复杂度为 O(1)
例2
// 计算fibonacci的空间复杂度?int[] fibonacci(int n) {long[] fibArray = new long[n + 1];fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n ; i++) {fibArray[i] = fibArray[i - 1] + fibArray [i - 2];}return fibArray;}
动态开辟了 N 个空间,空间复杂度为 O(N)
例3
// 计算阶乘递归Factorial的空间复杂度?long factorial(int N) {return N < 2 ? N : factorial(N-1)*N;}
递归调用了 N 次,开辟了 N 个栈帧,每个栈帧使用了常数个空间。空间复杂度为 O(N)

三、总结

        一段程序的优劣主要就由时间复杂度与空间复杂度决定,而这两者一般是很难兼得的,所以我们应该根据实际需求对代码进行调整,没有最好的代码,只有最合适的代码

那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。作者还是一个萌新,如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊

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

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

相关文章

我的 Android 性能书上架了!内附书籍介绍

大家好&#xff0c;我是拭心。 很高兴地向大家宣布&#xff0c;我的新书《Android 性能优化入门与实战》上架了&#xff01; 点击下面的小程序进行购买&#xff1a; 封面介绍 这本书的封面来自之前的投票文章 # 投票啦&#xff01;最新安卓进阶书籍封面由你来定&#xff0c;从四…

设计模式深度解析:深入浅出的揭秘游标尺模式与迭代器模式的神秘面纱 ✨

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 深入浅出的揭秘游标尺模式与迭代器模式的神秘面纱 开篇&#xff1a; 欢迎来到设计模式的神秘…

Unity 打包真机脚本丢失的问题

记录Bug Bug详情分析解决方案附录 Bug详情 项目中导入了UI Particle的Package,用于处理特效层级 unity 运行效果正常&#xff0c;打包真机后运行时发现特效并没有正确显示&#xff0c;真机Log如下图 需要接入查看真机Log工具的点这里 查看图中Log发现对应的Prefab上挂载的脚本…

【CSDN活动】程序员职业生涯的分水岭:年龄还是经验?

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 程序员职业生涯的分水岭&#xff1a;年龄还是经验&#xff1f;引言技术更新换代…

邮件营销工具的必备功能?如何选营销工具?

邮件营销工具的效果如何&#xff1f;营销工具怎么提升邮件营销&#xff1f; 一款优秀的邮件营销工具&#xff0c;不仅能够帮助企业高效地进行邮件发送&#xff0c;还能通过精准的数据分析和用户行为跟踪&#xff0c;提升营销效果。AokSend将探讨邮件营销工具的必备功能。 邮件…

Python机器学习赋能GIS:地质灾害风险评价的新方法论

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…

鉴源论坛丨形式化工程方法之需求建模(下)

作者 | 杨坤 上海控安可信软件创新研究院系统建模组 版块 | 鉴源论坛 观模 引言&#xff1a;需求建模是一种从源头确保软件质量的重要手段。需求建模可分为需求规约和需求确认两个部分&#xff0c;前者通过严格设计的形式化语言精确地将需求文档转换为了形式化规约&#xff0…

PASSL代码解读[01] readme

介绍 PASSL 是一个基于 PaddlePaddle 的视觉库&#xff0c;用于使用 PaddlePaddle 进行最先进的视觉自监督学习研究。PASSL旨在加速自监督学习的研究周期&#xff1a;从设计一个新的自监督任务到评估所学的表征。 PASSL 主要特性&#xff1a; 自监督前沿算法实现 PASSL 实现了…

为什么requests不是python标准库?

在知乎上看到有人问&#xff1a;为什么requests不是python标准库&#xff1f; 这确实是部分人困惑的问题&#xff0c;requests作为python最受欢迎的http请求库&#xff0c;已经成为爬虫必备利器&#xff0c;为什么不把requests直接装到python标准库里呢&#xff1f;可以省去第…

学习使用xbox手柄控制小乌龟节点移动

使用xbox手柄控制小乌龟&#xff0c;首先要下载joy功能包&#xff0c;发布sensor_msgs话题也就是手柄和ros通信的话题。 下载的步骤就根据官方文档即可 joy/Tutorials/ConfiguringALinuxJoystick - ROS Wiki 这里我提供一下具体步骤 第一步 安装joy 首先安装对应系统版本的…

【第二部分--Python之基础】02

二、运算符与程序流程控制 1、运算符 1.1 算术运算符 算术运算符用于组织整数类型和浮点类型的数据&#xff0c;有一元运算符和二元运算符之分。 一元算术运算符有两个&#xff1a;&#xff08;正号&#xff09;和-&#xff08;负号&#xff09;&#xff0c;例如&#xff1…

SV-7041VP SIP塑料壳sip音箱支持POE供电(白色弧形)

SV-7041VP SIP塑料壳sip音箱支持POE供电 &#xff08;白色弧形&#xff09; 一、描述18123651365微信 SV-7041VP是深圳锐科达电子有限公司的一款壁挂式SIP网络有源音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可…

QT的 纯代码+注释 学习笔记

QT学习笔记链接 更新到数据库操作为止..ing

微信怎么恢复聊天记录?效果惊人的3个方法

微信作为我们日常生活中最常用的即时通讯工具之一&#xff0c;承载着我们与亲友之间的重要沟通记录。然而&#xff0c;不可避免地会遇到误删聊天记录的情况&#xff0c;可能是因为手误、设备问题或其他原因。 当我们发现重要的聊天记录不见了&#xff0c;往往会感到焦虑和困扰…

题目:求和(蓝桥真题)

问题描述&#xff1a; 解题思路&#xff1a; 暴力超时&#xff0c;S变换得S a1*(a2.....an) a2*(a3....an) .... an-1*an。因此只需要求出括号内前缀和再相加求和即可。时间复杂度大大减小。 注意点&#xff1a;ans和前缀和的大小要开long long。 题解&#xff1a; #includ…

openGauss学习笔记-252 openGauss性能调优-使用Plan Hint进行调优-Scan方式的Hint

文章目录 openGauss学习笔记-252 openGauss性能调优-使用Plan Hint进行调优-Scan方式的Hint252.1 功能描述252.2 语法格式252.3 参数说明252.4 示例 openGauss学习笔记-252 openGauss性能调优-使用Plan Hint进行调优-Scan方式的Hint 252.1 功能描述 指明scan使用的方法&#…

论文:Term-Weighting Approaches in Automatic Text Retrieval翻译笔记(自动文本检索中的术语加权方法)

文章目录 论文标题&#xff1a;自动文本检索中的术语加权方法摘要1. 自动文本分析2. 词权重规范3. 术语加权实验4 推荐4.1 查询向量4.2 文档向量 论文标题&#xff1a;自动文本检索中的术语加权方法 论文链接&#xff1a;https://www.cs.colostate.edu/~howe/cs640/papers/sal…

javaWeb健康管理系统

一、引言 1.1 设计背景 紧张的工作节奏、教学和科研的压力、个人不良的工作生活习惯、以及伴随工作压力而来的家庭关系、人际关系紧张等因素使得高校群体成为慢性病的高发群体[1]。学生入学的定期体检&#xff0c;教职工人入职体检&#xff0c;以及所有学生和教职工的定期体检…

Leetcode 3.26

Leetcode Hot 100 一级目录1.每日温度 堆1.数组中的第K个最大元素知识点&#xff1a;排序复杂度知识点&#xff1a;堆的实现 2.前 K 个高频元素知识点&#xff1a;优先队列 一级目录 1.每日温度 每日温度 思路是维护一个递减栈&#xff0c;存储的是当前元素的位置。 遍历整个…

Ubuntu 下统计文件数量的命令

参考:https://blog.csdn.net/kxh123456/article/details/123811580 查看当前目录下的文件数量&#xff08;不包含子目录中的文件&#xff09; ls -l|grep "^-"| wc -l实例展示&#xff1a;如下图所示&#xff0c;当前路径下&#xff0c;有2个json文件和2个文件夹&a…