时间复杂度空间复杂度

news2025/1/10 1:44:55

算法效率

  • 数据结构
  • 算法
  • 时间复杂度
    • 大O的渐进表示法
    • 三种时间复杂度
  • 几道例题
    • 一.简单递归
    • 二结合代码来判断时间复杂度
  • 空间复杂度

我们程序猿开始的时候肯定听了不少的:数据结构和算法,那么阿涛就给大家说说自己的拙见吧.

数据结构

数据结构就是我们用来组织数据的方式,比如我们可以把一组数据储存在数组中,那么我们就是以数组的形式组织了这一组数据,针对不同的数据,我们会根据自己的需求使用不同的数据结构,后面我都会一一给大家介绍.

算法

现在好像高学历的人都在卷算法,其实就我目前了解到的算法,也就是人家给你一组数据,你按照要求给人家返回了一组数据,这就是广义的,我们都能接触到的算法实例,当然更加具体的详细的就需要我和大家日后深入地去学习了.

话说回来,我们通常都会把数据结构和算法二者放在一起去讨论,这是因为这两者之间是相辅相成的,不可能说你一个精通数据结构的人一点算法不懂,反之也是一个道理,那么这篇博客主要是给我们学习后面的集合类做出一个铺垫,所谓集合类就是有一个我们上学时期学过的集合的概念,里面存放的是好多好多的数据结构.

我们学习一切的一切的目的,往小了说就是为了能找到一份好的offer,往深了说,不就是为了提升自己,让自己成为一名优秀的程序猿码?那么我们通常评判一个程序猿的最基本手段就是看这个程序猿的代码写的怎么样:
同样的一个程序,你写的代码比别人的运行的快,占用的内存比别人小,你这代码写的可不就比别人好吗?
这就牵扯到了我们下面要讲的时间&&空间复杂度的概念!

请问兄弟们觉得我们现在是时间优先还是空间优先呢?从前因为技术的限制,内存做的都比较小,这种情况下我们就需要舍弃时间选择空间,但是现在一块内存/硬盘的价格被打下来了,这种情况下,时间就是金钱,其实说到底,只要你足够rich,一切问题都不再是问题了.

时间复杂度

我们可以把时间复杂度理解为程序运行的时间,那么是不是我们就应该记录下这个时间作为时间复杂度的值呢?受到一些客观因素的限制:
1.不同的设备. 2.不同的网速 3.打开不同的程序…
有了这诸多的条件限制,很多时候我们得到的程序运行时间并不具有绝对的参考价值,而且从现实的角度来说,一个程序只要写好了,我们就应该能知道它的时间复杂度,但是如果按照上述的说法,我们必须要时刻把电脑带在身边跑程序才能获得准确的时间复杂度,这显然是不科学的!
因此,我们想到一个程序的执行时间在理论上应该和这个程序执行操作的次数成正比,这个次数不受客观因素影响,只要程序写好了时间复杂度就存在在那里了.所以,我们日后将会使用大O的渐进表示法 来表示时间空间复杂度

大O的渐进表示法

public void test(int N){
	int x=0;
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){//第一个循环语句中,x++操作执行了N^2次
			x++;
		}
	}

	for(int i=0;i<4N;i++){
		x++                  //第二个循环语句中,执行了4N次操作
	}		
	
	int n=4;
	while(n!=0){
		x++;								//第三个循环语句中,执行了4次
		n--;
	}
}

那么我们用 F(N)=N^2+4N+4 来表示这个方法总的执行次数.
可是如果每次我们都需要这样计算这样表示这样子来比较时间复杂度,那会不会显得很麻烦?
所以我们规定了以下几条:
1. 常数项统统看成1;
2. 只保留最高次项;
3.去除系数项;
其实也不难想:当N很大的时候,其他的那一些花里胡哨的东西不过是跳梁小丑罢了,当执行语句是常数项使,对于计算机来说跟一条其实区别也不是很大,这样子极大程度上优化了我们对于时间复杂度的应用!

通常情况下我们讨论的都会是最差情况下的时间复杂度.

三种时间复杂度

就那寻找有N个元素的数组中某一个值的下标来举例子:
最好情况 :中头奖了,第一个就中了,那时间复杂度就是O(1);
平均情况 :我们遍历数组到一半才找到,时间复杂度(N/2) (仅仅是为了和下面的做出区别)
最坏情况 :倒了霉了,最后才碰到… 这种情况下我们需要遍历完数组:O(N)的时间复杂度!
这边我们主打的就是一个木桶效应,做程序猿可不敢赌,赌我这个程序没有bug,赌我这个时间复杂度很低,这样子是很不科学的一种方法,你要对得起你的工资啊!!

几道例题

一.简单递归

计算递归的时间复杂度:
public int sum(int n){
	if(n<=0) return 0;
	return sum(n-1)+n;
}

先说好:以后我们在表示时间复杂度的时候习惯性用N来表示问题的规模,N没有特殊的含义,就比如本题中的n就是N.
这里我们乍一看,似乎并没有执行语句啊,难道时间复杂度就是O(1)?
在递归中,我们的时间复杂度=递归次数 * 每个递归中执行语句的次数
在本题中我们的递归语句就是返回的语句,所以时间复杂度就是递归次数,也就是O(N).

public int sum(int n){
	if(n<=0) return 0;
	for(int i=0;i<N;i++){
		sout();
	}
	return sum(n-1)+n;
}

如果是这样的语句,每次递归中又包含循环之类的,那每个递归的执行语句就不是一了,这个方法目测时间复杂度为O(N)!

int fibonacci(int N) {
	return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);
}

之前的递归只有一层还好,那现在我们有两个递归了,我们又应该如何处理呢?
在这里插入图片描述
可以看到,我们现在每次递归下来还只是一个三目表达式,而我们需要递归的次数可以近似看成整个树的节点个数,现在我们根据等比数列求和公式可以推导出,时间复杂度是O(2^N),这里我们就发现了,有的时候时间复杂度跟我们想象的可能会有出入.

二结合代码来判断时间复杂度

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;
		else  
			return mid;
	} 
	return -1;
}

这是一个很普通的二分查找,按照普通的想法,我们是需要从两端往中间遍历完这个数组的,难道时间复杂度就是O(N)?并不是的,我们要深入代码去看,每一次循环结束,都能够筛掉一半的数据,因此我们从头到尾也只是遍历了一半的一半的一半…的数组长度,所以时间复杂度就应该是O(log N)!

空间复杂度

空间复杂度表示的是一个算法中临时占用存储空间大小的量度,跟时间复杂度一样,这个量度并不是绝对的占用的字节数大小,而是在进行整个算法的时候,我们创建的临时变量的大小.

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;
		else  
			return mid;
	} 
	return -1;
}

还拿这个二分查找举例子,虽然看似好像每次循环中我们都会创建一个mid变量,那么我们的空间复杂度是不是就是O(logN)呢?不是的,我们要考虑到一个因素是:在我们第二次进入循环创建变量时,第一次循环中创建的mid变量已经被回收了,等于就是说在整个函数栈帧的同一时刻,我们最多也就是创建了一个变量!

int fibonacci(int N) {
	return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);
}

在这里插入图片描述
再拿这个斐波那契举例子,虽然看似我们并没有在这个题目中创建变量,但是每一次我们递归下来都会开辟一个栈帧,栈帧也是相当耗费空间的好吧!
而且,对于这个递归来说,我们是一路向左开辟函数栈帧的,当左边的递归语句结束后,我们才会执行右边的,因此,对于整个方法来说,空间复杂度就是O(N)!

希望我的这篇博客能帮助到屏幕前的您!
百年大道,你我共勉!

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

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

相关文章

JVM-【面试题】-垃圾收集算法+垃圾收集器,以后就不用担心对象那些事了

一、垃圾收集算法在jvm里对可回收的对象在不同的垃圾收集器里&#xff0c;有不同的回收算法&#xff0c;具体的可以分为这四种&#xff1a;分代收集算法、复制算法、标记清除算法、标记整理算法1.1 分代收集算法当前虚拟机的垃圾收集都采用分代收集算法&#xff0c;这种算法没有…

【NI Multisim 14.0操作实例——最小锁存器电路】

目录 序言 &#x1f525;1.设置工作环境 &#x1f525;2.设置原理图图纸 &#x1f525; 3.设置图纸的标题栏 &#x1f525; 4. 增加元器件 &#x1f525; 5. 放置总线 &#x1f525; 6. 添加总线分支 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路…

ELasticSearch监控之Cerebro安装

文章目录安装包下载安装使用点击nodes 查看各节点状态点击rest发送可以发送请求查询数据安装包下载 https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro-0.9.4.tgzgit地址&#xff1a;https://github.com/lmenezes/cerebro 安装 将要包移动到/opt目录解…

Unity 3D 导入三维模型||Unity 3D 动画系统简介(Mecanim)

将三维模型导入 Unity 3D 是游戏开发的第一步。 下面以 3ds Max 为例&#xff0c;演示从三维建模软件中将模型导入 Unity 3D 的过程&#xff0c;具体步骤如下。 在 3ds Max 中创建房子模型。执行 Export → Export 命令导出 fbx 模型。设置保存路径以及文件名。选择默认设置选…

【transformers】tokenizer用法(encode、encode_plus、batch_encode_plus等等)

tranformers中的模型在使用之前需要进行分词和编码&#xff0c;每个模型都会自带分词器&#xff08;tokenizer&#xff09;&#xff0c;熟悉分词器的使用将会提高模型构建的效率。 string tokens ids 三者转换 string → tokens tokenize(text: str, **kwargs)tokens → strin…

安卓车机系统adb shell cmd 源码原理分析

hi&#xff0c;粉丝朋友们大家好&#xff01; 上一次视频分享了input专题课中input命令在android 12的更新&#xff0c;因为原来课程是基于android 10 &#xff08;可以加我扣&#xff1a;2102309716 优惠购买&#xff09; https://ke.qq.com/course/package/77595?tuin7d4eb3…

联合证券|金融部门开年推出新方案 改善优质房企资产负债状况

当时&#xff0c;努力促进房地产与金融正常循环是金融部门的工作要点之一。记者日前了解到&#xff0c;为遵循落实中心经济工作会议布置&#xff0c;有用防范化解优质头部房企危险&#xff0c;改进财物负债情况&#xff0c;有关部门起草了《改进优质房企财物负债表计划举动计划…

【计算机体系结构基础】流水线异常处理和提高流水线效率的技术(一)

流水线中的异常 异常的来源 外部事件指令执行中的错误数据完整性的问题地址转换异常系统调用陷入需要软件修正的运算 异常可以分为&#xff1a;可恢复异常和不可恢复异常 不可恢复异常&#xff1a;系统硬件出现严重故障&#xff0c;异常处理后系统面临重启。 解决办法&#x…

Spring Boot Apollo监听namespace并更新配置Bean(附源码)

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 背景 如果我们使用的配置中心是apollo的话我们经常会遇到这样的问题&#xff0c;就是动态更新配置Bean 动态更新配置bean 动态更新配置bean其实是很简单的&…

Python学习笔记-PyQt6消息窗

对话框是界面编程中重要的窗体&#xff0c;一般用于提示或者一些其他特定操作。一、使用QDialog显示通用消息框直接使用QDialog类&#xff0c;可以及通过对话框进行通用对话框显示&#xff0c;亦可以通过自定义设置自己需要的对话框。# _*_ coding:utf-8 _*_import sysfrom PyQ…

MySQL主从复制的原理是什么?

主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中&#xff0c;然后在从库上对这些日志重新执行(也叫重做)&#xff0c;从而使得从库和主库的数据保持同步。 MySQL支持一台主库同时向多台从库进行复制&#xff0c; 从库同时也可以作为其他从服务器的主…

Python批量下载某网站贵得要shi文档 并保存为PDF

人生苦短&#xff0c;我用Python 基本开发环境&#x1f4a8; Python 3.6Pycharm 相关模块的使用&#x1f4a8; import requests import parsel import re import os import pdfkit需要使用到一个软件 wkhtmltopdf 这个软件的作用就是把html文件转成PDF 想要把文档内容保存…

人工智能轨道交通行业周刊-第30期(2023.1.9-1.15)

本期关键词&#xff1a;贵阳智慧车站、城轨智能化汇总、隧道巡检、信创厂商、手语数字人 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与…

煤矿人员工服着装智能识别监测系统 yolov5架构

煤矿人员工服着装智能识别监测系统通过pythonyolov5深度学习网络架构&#xff0c;对画面中人员是否正确着装实时分析&#xff0c;发现违规着装立即抓拍存档告警。我们选择当下YOLO最新的卷积神经网络YOLOv5来进行识别检测。按照官方给出的数目&#xff0c;现版本的YOLOv5每个图…

数据库概述杂谈之章节回顾

数据与数据之间联系的模型表示 网状模型用“图”结构来表示数据及数据之间的联系层次模型用“树”结构来表示数据及数据之间的联系关系模型用“关系&#xff08;二维表&#xff09;”结构来表示数据及数据之间的联系对象模型用“对象”数据结构来表示数据及数据之间的联系 数…

SPI协议与GPIO模拟SPI的实现

SPI定义 SPI&#xff08;Serial Peripheral Interface, 串口外设接口&#xff09;&#xff0c;它用于MCU与各种外围设备以串行方式进行通信&#xff0c;速度最高可达25MHz以上。 SPI接口主要应用在EEPROM、 FLASH、实时时钟、网络控制器、 OLED显示驱动器、 AD转换器&#xf…

ArcGIS10.6保姆式安装教程,超详细;附安装包

安装前请关闭杀毒软件&#xff0c;系统防火墙&#xff0c;断开网络连接 参考链接&#xff1a;请点击 下载链接&#xff1a; 通过百度网盘分享的文件&#xff1a;ArcGIS10.6zip 链接:https://pan.baidu.com/s/1tCsOQ_-WP-usEHmJo9SfcA 提取码:hn15 复制这段内容打开「百度网盘A…

Java环境安装、python环境安装、Burpsuite安装

数据来源 Java环境安装 Windows安装JDK8&#xff08;安装过程&#xff1a;一路下一步&#xff09; 下载JDK8&#xff1a;https://www.oracle.com/java/technologies/javase-jdk8-downloads.html 百度网盘&#xff1a;windows64、84位 配置PATH环境变量&#xff1a; 变量名…

RT-Thread系列--双链表分析

一、目的学习过C语言的同学应该都知道几种常用的数据结构&#xff0c;例如数组、单链表、双链表等。每种数据结构都有其特点和应用场景&#xff0c;本篇就结合RT-Thread源码分析一下其双链表实现细节和特点。那什么是双链表呢&#xff0c;这边简单解释一下帮助大家理解。通过双…

KubeSphere 开源社区 2022 年度回顾与致谢

2022 年&#xff0c;国内的云原生技术生态日趋完善&#xff0c;细分技术项目也不断涌现&#xff0c;形成了完整的支撑应用云原生化的全生命周期技术体系。基础设施即代码、微服务、Serverless 等技术&#xff0c;促使基础设施资源向更加灵活弹性、自动化方向发展。而开源生态也…