数据结构小知识------时间与空间复杂度

news2024/11/25 1:46:14

本章思维导图:

 一,时间复杂度

1.1时间复杂度的概念

🌐:什么是时间复杂度呢?时间复杂度其实就是一个程序运行时它的指令运行的次数

在这里,程序默认每条指令的运行时间是一样的。所以时间复杂度就可以理解为是程序内指令的运行次数。

说一千道一万,不如来个例子:

🌰:时间复杂度为O(n)

int main() {
	int i = 0;
	int n = 0;
	scanf("%d", &n);
	for (i = 0;i < n;i++) {
		printf("执行%d次\n", i+1);
	}
	return 0;
}

这个程序的时间复杂度便是O(n),这个程序的时间复杂度的计算其实就看for循环的执行次数,很明显for循环会执行n次,所以这个程序的时间复杂度是O(n)。

🌰:时间复杂度为O(n^2)

int main() {
	int i = 0;
	int j = 0;
	int n = 0;
	scanf("%d", &n);
	for (i = 1;i <= n;i++) {
		for (j = 1;j <= n;j++) {
			printf("执行了%d次\n", i * j);
		}
	}
	return 0;
}

这个程序的时间复杂度便是O(n^2),因为这个程序有两个for循环。当第一层循环计算一次时,第二层循环就要计算n次。所以当第二层循环计算了n次时整个程序就计算了n^2次。所以这个程序的时间复杂度是O(n^2)。

1.2时间复杂度的计算

🌐:细心的小伙伴一定会发现我在对时间复杂度进行描述的时候使用了O()的表示方法。这个表示方法其实就叫作大O表示法。在算法导论里面,大O表示法表示的就是算法在最坏的情况下的运行时间。

1.2.1:大O表示法的几个计算特点

1.只保留最高阶的项

🌐因为计算机的运算速度十分的快,所以在一个程序内可能只有最高阶的项可以影响它。所以在我们使用大O表示法的时候,就可以舍弃其它项只保留最高阶的项来对程序的运行速度进行表示。在这里也表明了大O表示法注定是一个估计的值而不是一个精确的值。

举个例子:🌰

int main() {
	int i = 0;
	int j = 0;
	int n = 0;
	scanf("%d", &n);
	for (i = 1;i <= n;i++) {
		printf("执行了%d次\n", i);
	}
	for (i = 1;i <= n;i++) {
		for (j = 1;j <= n;j++) {
			printf("执行了%d次\n", i * j);
		}
	}
	return 0;
}

在这里,很明显我写的这个程序的执行次数是n+n^2次。但是当我们用大O表示法的时候,我们是不会用O(n+n^2)来表示。我们用的还是用O(n^2)来表示。因为在使用大O表示法时我们只保留最高阶的项。在这里就是n^2。

2.常数次用O(1)表示

🌐在程序中,如果指令只使用了常数次的话,那我们就可以用O(1)来表示这个程序的时间复杂度。不管这个常数有多大它的时间复杂度都是O(1),这是因为计算机的运行速度实在是太快了。

 举个例子:🌰

int main() {
	int i = 0;
	for (i = 0;i < 5;i++) {
		printf("执行%d次\n", i);
	}
	return 0;
}

这个5是常数,所以这个for循环执行的次数是常数次。因此,这个代码的时间复杂度就是O(1)

int main() {
	int i = 0;
	for (i = 0;i < 50000000;i++) {
		printf("执行%d次\n", i);
	}
	return 0;
}

现在把5换成50000000,即使大小变大了很多。但是50000000还是一个常数,所以这个代码的时间复杂度还是O(1)。

3.大O表示法里的logn的底数是2 而不是10

🌐我们大多数的初学者可能已经习惯了logn的底数是10了,但是要时刻记住在计算机中logn的底数是2。

二,空间复杂度

2.1空间复杂度的概念

🌐什么是空间复杂度呢?空间复杂度就是一个算法在运行过程中占用内存空间的大小的度量。这个内存空间与执行文件的大小没有半毛钱的关系。也就是说时间复杂度与执行文件的大小没有关系。

 举个例子:

🌰

int main() {
	int i = 0;
	int n = 0;
	scanf("%d", &n);
	for (i = 0;i < n;i++) {
		printf("执行%d次\n", i+1);
	}
	return 0;
}

这个程序的空间复杂度便是O(1),因为这个程序创建的变量是可数的,只有2个。所以它的空间复杂度就是O(1)

int main() {
	int i = 0;
	int n = 0;
	scanf("%d", &n);
	int arr[] = { 0 };
	for (i = 0;i < n;i++) {
		arr[i] = i;
	}
	return 0;
}

 像这个代码的空间复杂度便是O(n)因为这个代码要开辟n个空间大小的数组,所以这个程序的空间复杂度就是O(n)。

 2.2空间复杂度的计算

空间复杂度的计算其实时间复杂度的计算差不多,只是计算的对象从时间变成了空间。

只要套用时间复杂度的计算方法,然后再将计算时间变成计算空间就可以了。

3.斐波那契数列的时间与空间复杂度的计算方法 

3.1斐波那契数列的介绍

 斐波那契数列又名兔子数列,像:1,1,2,3,5,8,13,21,34,55,89

这样的数列就是一个斐波那契数列。可以很明显的看出斐波那契数列的特点是从第三项开始,每一项都等于前两项的和。

现在我们来编写一个代码来求斐波那契数列的第n项的结果:

代码如下:

int Fib(int n) {
	if (n <= 0) {
		return 0;
	}
	else if (n == 1) {
		return 1;
	}
	else {
		return Fib(n - 1)+Fib(n-2);
	}

}
int main() {
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d\n", ret);
	return 0;
}

 这段代码确实容易写出来,但现在的问题是:这段代码的时间复杂度是多少呢?空间复杂度是多少呢?

3.1时间复杂度

要算时间复杂度,其实就是要算这个递归调用了多少次Fib()函数。那我们只要求出这段代码调用了多少次Fib函数便大功告成了。

3.2 计算时间复杂度

 现在假设n==5,计算一下时间复杂度。计算这个时间复杂度便是要计算函数Fib被调用的次数,现在我借助图像来详细介绍一下Fib函数被调用的次数:

在这个图里面,可以清楚的数出来这个图里面的节点数有15个。当我们用一个阶乘的方式来表示15时,15==2^(n-1)-1==(2^n)/2-1。当我们用大O 表示法来表示的时候就变成了O(2^n)。(只保留最高一层项)。

3.3空间复杂度

这个斐波那契数列的空间复杂度是什么呢?众说周知,空间复杂度表示的是在一个程序在运行时开辟的空间大小。在递归中这个空间该怎么算了?递归中的空间复杂度是:递归深度*每次递归时的空间复杂度。像上面的Fib(5)的空间复杂度就是O(1)*5。递归的空间复杂度就是O(5)。当我们将这个空间复杂度一般化时,它的空间复杂度就是O(n)。

3.4优化

可以看到这个递归的时间复杂度是非常大的,当n非常大的时候这种递归的方法的耗时就会非常长。所以我们要对这个递归方法进行优化来让它变得高效一点。在这里优化的目的就是减少递归的次数,也就是将return Fib(n-1)+Fib(n-2)改一下。

 优化:时间复杂度

int Fib(int first, int second, int n) {
	if (n <= 0) {
		return 0;
	}
	else if (n < 3) {
		return 1;
	}
	else if (n == 3) {
		return first + second;
	}
	else {
		return Fib(second, first + second, n - 1);//将两次递归改为一次
	}


}
int main() {
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(1,1,n);
	printf("%d\n", ret);
	return 0;
}

这个程序的时间复杂度是多少呢?答案是O(n),空间复杂度也是O(n)。

再次优化:优化空间复杂度

int main() {
	int a = 1;
	int b = 1;
	int c = 1;
	int n = 0;
	scanf("%d", &n);
	n = n - 2;
	while (n--) {
		c = a + b;
		a = b;
		b = c;
	}
	printf("%d\n", c);
	return 0;
}

这个程序的空间复杂度就是O(1),时间复杂度还是O(n).

结束,今天的分享就到此为止,谢谢你的阅读。 

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

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

相关文章

【云原生进阶之容器】第六章容器网络6.4.2--Flannel的安装与部署

1 flannel的安装与部署 见链接一篇文章带你了解Flannel - Flannel - 操作系统 - 深度开源 1.1 部署环境规划 1.2 安装部署 #tar -xf flannel-v0.13.0.tar.gz #mv /apps/svr/flannel-v0.13.0 #ln –svfn /apps/svr/flannel-v0.13.0 /apps/svr/flannel 1.2.1 调整Flannel配置…

设计模式(超详细)

设计模式 原则 什么是SOLID原则&#xff1f; S单一职责SRP Single-Responsibility Principle 一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合,高内聚在面向对象原则的引申,将职责定义为引起变化的原因,以提高内聚性减少引起变化的原因。 比如…

项目资源管理流程:五步专业指南

项目资源管理是描述大多数项目经理的一项关键职能的方式——收集完成工作所需的团队成员、设备和其他材料&#xff08;也称为资源&#xff09;。 以下是项目资源管理的步骤清单&#xff1a; 步骤1&#xff1a;资源规划 为了确定完成项目的资源需求&#xff0c;你首先需要了…

SpringCloud-Gateway实现网关

网关作为流量的入口&#xff0c;常用的功能包括路由转发、权限校验、限流等Spring Cloud 是Spring官方推出的第二代网关框架&#xff0c;由WebFluxNettyReactor实现的响应式的API网关&#xff0c;它不能在传统的servlet容器工作&#xff0c;也不能构建war包。基于Filter的方式提…

个人开发者如何选择阿里云服务器配置CPU内存带宽?

阿里云服务器个人用怎么选择&#xff1f;云服务器吧建议选择ECS共享型s6&#xff0c;不限制CPU性能&#xff0c;选择1核2G或2核4G都可以&#xff0c;云服务器s6处理器采用2.5 GHz主频的Intel Xeon Platinum 8269CY&#xff08;Cascade Lake&#xff09;&#xff0c;睿频3.2 GHz…

【论文阅读--WSOL】Spatial-Aware Token for Weakly Supervised Object Localization

文章目录方法实验Limitation论文&#xff1a;https://arxiv.org/abs/2303.10438代码&#xff1a;https://github.com/wpy1999/SAT/blob/main/Model/SAT.py方法 这篇文章的方法应该属于FAM这一类。 额外添加的一个spatial token&#xff0c;从第10-12层开始&#xff0c;利用其得…

Vue3技术1之Vue3简介、创建Vue3工程、分析工程结构、安装开发者工具与初识setup

Vue3技术1Vue3简介发展提升创建Vue3工程使用vue-cli创建使用vite创建分析工程结构&#xff08;由vue-cli创建的&#xff09;main.jsvue.config.jsApp.vue安装开发者工具初识setupsetup的两种返回值返回一个对象App.vue返回一个函数App.vueVue2与Vue3混合使用App.vue总结Vue3简介…

【致敬未来的攻城狮计划】— 连续打卡第一天:提前对CPK_RA2E1是瑞萨RA系列开发板的初体验,了解一下(文字上的初理解)

系列文章目录 系列文章目录 前言 一、瑞萨MCU&#xff08;CPK_RA2E1是瑞萨RA系列开发板&#xff09;是什么&#xff1f; 首先引入是什么&#xff1f; 他的优势在哪&#xff1f; 瑞萨CPK_RA2E1 对标stm32 相似之处和不同之处&#xff1f; 瑞萨CPK_RA2E1如何开发&#xff…

集成定时器事件

一&#xff0c;定时器事件 1、概述 libevent提供了高性能定时器的功能&#xff0c;方便执行延迟回调逻辑。在添加事件监听的时候&#xff0c;可以不指定fd和监听的事件&#xff0c;指定超时的时间&#xff0c;实现定时器功能。定时器的实现主要依赖下面的数据结构&#xff0c;…

java 多线程基础 万字详解(通俗易懂)

目录 一、前言 二、定义 1.进程 : 2.线程 : 3.单线程与多线程 : 4.并发与并行 : 三、线程的创建 1.创建线程的两种基本方式 : 1 继承Thread类&#xff0c;并重写run方法 1.5 多线程的执行机制(重要) 2 实现Runnable接口&#xff0c;并重写run方法 2. 两种创建线程方式…

【C++】继承---下(子类默认成员函数、虚继承对象模型的详解等)

前言&#xff1a; 上篇文章我们一起初步了解了继承的概念和使用&#xff0c;本章我们回家新一步深入探讨继承更深层次的内容。 前文回顾——>继承---上 目录 &#xff08;一&#xff09;派生类的默认成员函数 &#xff08;1&#xff09;6个默认成员函数 &#xff08;…

Pytorch全连接神经网络实现手写数字识别

问题Mnist手写数字识别数据集作为一个常见数据集&#xff0c;包含10个类别&#xff0c;在此次深度学习的过程中&#xff0c;我们通过pytorch提供的库函数&#xff0c;运用全连接神经网络实现手写数字的识别方法设置参数input_size 784hidden_size 500output_size 10num_epoc…

JavaScript对象类型之function

目录 一、Function 定义函数 调用函数 默认参数 匿名函数 箭头函数 二、函数是对象 三、函数作用域 四、闭包 五、let、var与作用域 一、Function 定义函数 function 函数名(参数) {// 函数体return 结果; } 例如&#xff1a; function add(a, b) {return a b; …

应届生通过Java培训班转行IT有前途吗?

借用邓小平同志曾说过的一句话&#xff1a;科学技术是第一生产力。IT行业作为科技行业中的一员&#xff0c;不管是在自身的发展&#xff0c;还是支持其他行业的发展中都扮演了不可或缺的角色&#xff0c;“互联网”是社会发展的趋势&#xff0c;前途是无限的。而计算机语言是目…

dolphinscheduler之hivecli 任务

hivecli 任务 Hivecli任务说明 dolphinscheduler的hivecli任务是专门执行hivesql的任务类型。其中子类型分为FROM_SCRIPT和FROM_FILE。 FROM_SCRIPT 执行的脚本可以直接在文本框中编写 执行的底层采用-e参数执行 hive -e "show databases;show tables"FROM_FILE…

建造者模式解读

目录 话题引进 传统方式解决盖房需求 传统方式的问题分析 建造者模式基本介绍 基本介绍 四个角色 原理类图 ​编辑 应用实例 改进代码 建造者模式在 JDK 的应用和源码分析 建造者模式的注意事项和细节 抽象工厂模式 VS 建造者模式 话题引进 1) 需要建房子&#xff1a;…

剑指 Offer (第 2 版)

&#xff08;简单&#xff09;剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请…

Python实现采集某二手房源数据并做数据可视化展示

目录环境介绍&#xff1a;模块使用:实现爬虫思路&#xff1a;代码环境介绍&#xff1a; Python 3.8Pycharm 模块使用: requests >>> pip install requests 数据请求模块 parsel >>> pip install parsel 数据解析模块 csv 内置模块 实现爬虫思路&#x…

如何搭建自己的V Rising自建服务器,以及常见的V Rising服务器问题解决方案

V rising官方服务器经常无法连接&#xff0c;无法和小伙伴玩耍&#xff1b;如何搭建自己的V rising服务器呢&#xff1f;还可以修改掉落倍率&#xff0c;加快游戏进度&#xff0c;搭建自己的私人服务器。 前言 最近V rising这个游戏很火呀&#xff0c;迫不及待地和小伙伴一起…

基于粒子群优化算法的面向综合能源园区的三方市场主体非合作交易方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…