数据结构——时间复杂度和空间复杂度

在这里插入图片描述
1.算法效率
2.时间复杂度
3.空间复杂度
4. 常见时间复杂度以及复杂度oj练习

1.算法效率
1.1 如何衡量一个算法的好坏

如何衡量一个算法的好坏呢?比如对于以下斐波那契数的计算

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

我们看到虽然用递归的方式实现斐波那契很简单,但是简单一定代表效率高吗?
我们接着往下看。
1.2 算法的复杂度
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般
是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算
机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计
算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
1.3 复杂度在校招中的考察
在这里插入图片描述
我们可以看到在校招笔试的时候可能会遇到一些问题,就是它限制了时间和空间的复杂度,这无疑是加大了难度,所以我们现要了解什么是时间和空间复杂度,这样才能去写这道题。
2.时间复杂度
2.1 时间复杂度的概念
时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一
个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知
道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个
分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法
的时间复杂度。
即:找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。
// 请计算一下Func1中++count语句总共执行了多少次?

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;
	}

通过我们的精确计算,count总共经过了N^2+2*N+M.
Func1 执行的基本操作次数 :
N = 10 F(N) = 130
N = 100 F(N) = 10210
N = 1000 F(N) = 1002010

所以当N特别大的时候后面可以忽略掉。
所以上面的代码的时间复杂度是O(N^2).

实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这
里我们使用大O的渐进表示法。

2.2 大O的渐进表示法
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为O(N^2).
通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
另外有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

2.3常见时间复杂度计算举例

// 计算Func2的时间复杂度?
void Func2(int N)
{
	int count = 0;
	for (int k = 0; k < 2 * N; ++k)
	{
		++count;
	}
	int M = 10;
	while (M--)
	{
		++count;
	}
	printf("%d\n", count);
}

这个count的准确次数是2*N+M
所以写成大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;
	}
	printf("%d\n", count);
}

这里就要看前提是什么,如果不知道M和N的话,我们就可以写成O(M+N),如果M和N一样的话,可以写成O(N),如果N比M大的多,就可以写成O(N),反之则为O(M)。

// 计算Func4的时间复杂度?
void Func4(int N)
{
	int count = 0;
	for (int k = 0; k < 100; ++k)
	{
		++count;
	}
	printf("%d\n", count);
}

常数项其实就是O(1)因为我们的计算机的运行速度特别快,每秒十几亿的速度,所以常数项都可以写成O(1).

// 计算strchr的时间复杂度?
const char * strchr ( const char * str, int character );

在这里插入图片描述
意思就是找一个字符,有就返回字符位置,没有就返回空指针,所以这肯定要遍历一遍我们的字符串,所以是O(N)。

// 计算BubbleSort的时间复杂度?
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;
	}
}

冒泡排序我们写的第一个是它的趟数,然后进行前后进行比较,如果有n个数,那第一次要比较的是n-1次,接下来,比如我们是升序的话,最后一个数就排好了,并且是最大的一个数,所以第二次就可以忽略最后一个数的比较,接下来就是n-2,这样下去一直到1,所以将他们相加,是(N^2-N)/2,当N无穷大的时候,所以大O就可以写成O(N*N).最快只需要n-1次就可以了

// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x)
{
	assert(a);
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int mid = begin + ((end - begin) >> 1);
		if (a[mid] < x)
			begin = mid + 1;
		else if (a[mid] > x)
			end = mid;
		else
			return mid;
	}
	return -1;
}

我们的二分查找时间复杂度可快了,是效率非常高的一个排序。
它的算法时间复杂度是O(log2N),可以写成logN,底数是2.
为什么说他快呢,举个例子,比如我们要在14亿人中要找出有个人,最坏情况只要31次,第一次直接去掉了7亿人,第二次又是一半,所以效率快。

//计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
	if (0 == N)
		return 1;
	return Fac(N - 1) * N;
}

其实它递归了N次,那就很简单,就是O(N)。

// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{
if(N < 3)
return 1;
return Fib(N-1) + Fib(N-2);
}

通过计算分析发现基本操作递归了2N次,时间复杂度为O(2N),因为我们第一次是2的1次,后面就是2的2次,一直到2的n次,相加就可写成O(2^N),所以递归并不是效率特别高的算法有时候,但是它简洁。

今天的分享就到这里,我们下次再见

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

火爆全网,HttpRunner自动化测试框架-CSV文件数据(详细总结)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 当数据量比较大的…

使用iPad和Procreate绘制古风插画设计教程

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 前言 随着数字绘画工具…

四、web应用程序技术——HTTP

文章目录 1 HTTP请求2 HTTP响应3 HTTP方法4 URL5 HTTP消息头5.1 常用消息头5.2 请求消息头5.3 响应消息头 6 cookie7 状态码8 HTTP代理9 HTTP身份验证 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是访问万维网使用的核心通信协议&…

【JavaEE进阶】Spring 更简单的读取和存储对象

文章目录 一. 存储Bean对象1. 配置扫描路径2. 添加注解存储 Bean 对象2.1 使用五大类注解存储Bean2.2 为什么要有五大类注解&#xff1f;2.3 有关获取Bean参数的命名规则 3. 使用方法注解储存 Bean 对象3.1 方法注解储存对象的用法3.2 Bean的重命名3.3 同⼀类型多个 Bean 报错 …

国产芯力特Mini LIN SBC SIT1028Q应用方案,可替代TJA1028

SIT1028Q是一款内部集成高压LDO稳压源的本地互联网络&#xff08;LIN&#xff09;物理层收发器&#xff0c;可为外部ECU&#xff08;Electronic Control Unit&#xff09;微控制器或相关外设提供稳定的5V/3.3V电源&#xff0c;该LIN收发器符合LIN2.0、LIN2.1、LIN2.2、LIN2.2A、…

应急响应-linux挖矿病毒的实战处置

0x01 服务器现状分析 客户描述服务器卡顿&#xff0c;切通过搜索引擎进去该官网跳转非法页面&#xff0c;但本地访问无异常 0x02 信息收集 通过进程占用情况cpu功率拉满&#xff0c;确定被植入挖矿病毒文件 qq 且存在计划任务update.sh&#xff1a;crontab -l 将该文件上传沙…

Java课题笔记~ HTTP协议(请求和响应)

Servlet最主要的作用就是处理客户端请求&#xff0c;并向客户端做出响应。为此&#xff0c;针对Servlet的每次请求&#xff0c;Web服务器在调用service()方法之前&#xff0c;都会创建两个对象 分别是HttpServletRequest和HttpServletResponse。 其中HttpServletRequest用于封…

【WebService】使用postman调用WebService方法

1、需求 公司原来有一个项目使用的是WebService&#xff0c;想模拟一下怎么调用WebService的方法&#xff0c;使用postman调用怎么调用。 2、postman方式 接口&#xff1a;http://127.0.0.1:8080/SecurityWebService/SecurityCommand?wsdl 对应你的代码配置&#xff1a; …

模拟实现消息队列项目(系列4) -- 服务器模块(内存管理)

目录 前言 1. 创建MemoryDataCenter 2. 封装Exchange 和 Queue方法 3. 封装Binding操作 4. 封装Message操作 4.1 封装消息中心集合messageMap 4.2 封装消息与队列的关系集合queueMessageMap的操作 5. 封装未确认消息集合waitMessage的操作 6. 从硬盘中恢复数据到内存中 7. Memo…

介绍另外一个容器技术, Apptainer

一说到容器&#xff0c;我们往往会脱口而出&#xff0c; Docker&#xff0c; 实际上Docker 仅仅是Linux 容器化的一种&#xff0c; 今天介绍的Apptainer 就是另外一种容器技术。 那么Apptainer 具体是一个什么东西呢&#xff1f; 跟Docker 有什么区别呢&#xff1f; 首先&#…

【Python】python通过cmd创建虚拟环境(pip方式)

前言&#xff1a; 在window中使用pipenv创建虚拟环境时&#xff0c;虚拟环境默认的位置是在C:\User\Administrator\.virtualenvs\目录下&#xff1b;那如果我们想配置到自定义位置&#xff0c;该如何修改呢&#xff1f;当我们在进行python项目开发的时候&#xff0c;为了不让项…

tcl学习之路(四)(vivado设计分析)

1.FPGA芯片架构中的对象 在打开elaborated/synthesied/implemented的情况下&#xff0c;可使用如下命令获取期望的SLICE。SLICE分为SLICEL和SLICEM&#xff0c;由LUT、FF、MUX、CARRY组成。 set all_slice [get_sites SLICE*] set col_slice [get_sites SLICEX0Y*] set all_sl…

【资料分享】全志科技T507-H工业核心板规格书

1 核心板简介 创龙科技SOM-TLT507是一款基于全志科技T507-H处理器设计的4核ARM Cortex-A53全国产工业核心板&#xff0c;主频高达1.416GHz。核心板CPU、ROM、RAM、电源、晶振等所有元器件均采用国产工业级方案&#xff0c;国产化率100%。 核心板通过邮票孔连接方式引出MIPI C…

【爱书不爱输的程序猿】内网的摄像头,远程进行访问的方式方法

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 快速远程访问内网的摄像头【内网穿透】 前言一、快速远程访问内网的摄像头1. 打开“允许远程桌面”开关2. 建立TCP-IP隧道3. 获取生成的TCP-IP隧道地址4. 连接另一台电脑4.1 取得该…

Python自动化测试基础必备知识点总结

目录 一、自动化测试的概念 二、Python自动化测试基础必备知识点 一、自动化测试的概念 性能系统负载能力稳定性过载操作下的系统瓶颈自动化测试&#xff0c;使用程序代替人工&#xff0c;可以提高测试效率性&#xff0c;自动化测试能自动化使用代码模拟大量用户&#xff0c…

java+springboot+mysql小区宠物管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的小区宠物管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff1b;宠物分类&#xff1b;宠物管理&…

【Unity细节】Unity打包后UI面板消失是怎么回事

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏&#xff1a;unity细节和bug ⭐关于物体的动画碰到其他碰撞器后停止播放的问题⭐ 文章目录 ⭐关于物体的动画碰…

Netty:用forEachByte遍历处理ByteBuf中的可读字节

说明 io.netty.buffer.ByteBuf的forEachByte(ByteProcessor processor)用指明的ByteProcessor 遍历ByteBuf中的可读字节。遍历的时候用升序遍历。 -这个函数可以在ByteBuf中寻找某个字节首次出现的位置&#xff0c;或者首次不是某个字节的位置。 如果已经遍历完了可读字节但还…

Spring Cloud Gateway

一 什么是Spring Cloud Gateway 网关作为流量的入口&#xff0c;常用的功能包括路由转发&#xff0c;权限校验&#xff0c;限流等。 Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架&#xff0c;定位于取代 Netflix Zuul。相比 Zuul 来说&#xff0c;Spring Clo…

Unity背包系统与存档(附下载链接)

下载地址: https://download.csdn.net/download/qq_58804985/88184776 视频演示: 功能: 拖动物品在背包中自由移动,当物品拖动到其他物品上时,和其交换位置.基于EPPlus的背包数据与位置保存 原理: 给定一个道具池表格与一个背包表格 道具池表格负责存储所有道具的信息 背…