【时间复杂度和空间复杂度之间的故事】

【时间复杂度和空间复杂度之间的故事】

      • 一.前言
  • 二.时间复杂度
      • 定义
      • 时间复杂度的计算规则
      • 习题
  • 三.空间复杂度
      • 定义
      • 计算方法
      • 习题
      • 空间复杂度 O(1)
      • 空间复杂度 O(n)

本文主要讲解关于时间复杂度与空间复杂度
😀😃😁😁😇😇
在这里插入图片描述

😀😃😁😁😇😇

一.前言

时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间。在计算机发展的早期,计算机的存储容量很小,所以对空间复杂度很是在乎。但是随着计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。这就是为什么我们大多时候听到的是时间复杂度,而很少听到空间复杂度的原因。

二.时间复杂度

定义

  1. 时间复杂度就是用来方便开发者估算出程序的运行时间
  2. 我们该如何估计程序运行时间呢,我们通常会估计算法的操作单元数量,来代表程序消耗的时间,
    这里我们默认CPU的每个单元运行消耗的时间都是相同的。
  3. 假设算法的问题规模为n,那么操作单元数量便用函数f(n)来表示
  4. 随着数据规模n的增大,算法执行时间的增长率和f(n)的增长率相同,这称作为算法的渐近时间复杂度,简称时间复杂度,记为 O(f(n))
  5. 这里就要说一下这个大O,什么是大O呢,很多同学说时间复杂度的时候都知道O(n),O(n^2),但说不清什么是大O,算法导论给出的解释:大O用来表示上界的,当用它作为算法的最坏情况运行时间的上界,就是对任意数据输入的运行时间的上界。
    😀😃😁😁😇😇

时间复杂度的计算规则

  • 基本操作即只有常数项,认为其时间复杂度为O(1)
  • 顺序结构,时间复杂度按加法进行计算
  • 循环结构,时间复杂度按乘法进行计算
  • 分支结构,时间复杂度取最大值
  • 在没有特殊说明时,我们所分析的时间复杂度都是指最坏时间复杂度
  • 判断一个算法效率时,往往只需要关注操作数量的最高次项,其他次要项和常数项可以忽略

注:递归算法的时间复杂度 = 递归的次数 * 每次递归函数中的次数。

习题

例一

int result = 100; //运行程序只执行一次  
 
result ++ ;  //执行一次
 
System.out.println ("Hello!"+result);

上面算法的运行的次数的函数为f(n)=3,根据推导大O阶的规则1,每次运行程序每条语句执行一次,所以这个算法的时间复杂度仍旧是O(1),我们可以称之为常数阶。

例二

void fun4(int N) {
	int count = 0; 
	for (int k = 0; k < 100; k++) {
		++count;
	}
	printf("%d\n", count);
}

fun3的基本操作的执行了100次,通过推导大O阶方法知道,时间复杂度为O(1),也就是执行次数为常数。

例三

for(int i=0;i<n;i++){
 
   System.out.println(result[i]);  //执行一次
 
}

上面算法循环体中的代码执行了n次,因此时间复杂度为O(n),实际上,在for循环里面的所有时间复杂度为O(1)的语句总的时间复杂度都是O(n)。

例四

int result=1;
 
while(result<n){
 
    result=result*2; //时间复杂度为O(1)
 
}

可以看出上面的代码, result=result*2; 随着result每次乘以2后,都会越来越接近n,当result大于等于n时就会退出循环(限制条件)。

如果循环的次数为T,所以2^T=n于是T=log₂n,因此得出这个算法的时间复杂度为O(logn)。

例五

//二分查找法
int BinarySearch(int* a, int  n, int x) {
	assert(a);
	int begin = 0;
	int end = n - 1;
	
	while (begin < end) {
	
		int mid = ((end - begin) >> 1) + begin; //计算end与begin的中间值,右移1位相当于除以2
		
		if (a[mid] < x) {begin = mid - 1;}
		else if(a[mid]>x){end = mid;}
		else {return mid;}
		
	}
	
	return -1;
}

时间复杂度为:O(logN)。分析如下:

第一次查找:在长度为N的数组中查找值,取中间值进行比较
第二次查找:在长度为N/2的数组中查找值,取中间值进行比较
第三次查找:在长度为N/(2^2)的数组中查找值,取中间值进行比较
第logN次查找:在长度为N/(2^logN)的数组中查找值,即在长度为1的数组中查找,无论是否找到均跳出循环,结束查找

例六

  for(int i=0;i<n;i++){       
       for(int j=0;j<n;j++){     
           System.out.println(result[i][j]);  //执行一次     
       }     
    }

这是一个循环嵌套的语句,很明显内层循环的时间复杂度在讲到线性阶时就已经得知是O(n),又经过了外层循环n次,那么这段算法的时间复杂度则为O(n²)。

例七

void fun(int n){
    int i,j,x=0;
    for(i=1;i<n;i++){
       for(j=n;j>=i+1;j--){
           x++;
       }
    }
}

在这里插入图片描述

例八

void fun(int n){
    int i=0;
    while(i*i*i<=n){
        i++;
    }
}

在这里插入图片描述
例九

// 多个复杂度组合
 
for(int i=0;i<n;i++){   
   for(int j=0;j<n;i++){ 
       System.out.println(result[i][j]);  //执行一次 
   } 
}
 
for(int i=0;i<n;i++){  
   System.out.println(result[i]);  //执行一次 
}

对于顺序执行的语句或者算法,总的时间复杂度等于其中最大的时间复杂度。所以对于以上的代码,时间复杂度为O(n²)。

例十

// 多个复杂度组合
if(flag){ 
   for(int i=0;i<n;i++){  
       for(int j=0;j<n;i++){ 
          System.out.println(result[i][j]);  //执行一次 
       } 
    } 
}else{ 
    for(int i=0;i<n;i++){   
       System.out.println(result[i]);  //执行一次 
    } 
}

对于条件判断语句,总的时间复杂度等于其中时间复杂度最大的路径的时间复杂度。所以对于以上的代码,时间复杂度为O(n²)。
在这里插入图片描述

三.空间复杂度

定义

既然时间复杂度不是用来计算程序具体耗时的,那么我也应该明白,空间复杂度也不是用来计算程序实际占用的空间的。
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势,我们用 S(n) 来定义。
😀😃😁😁😇😇

计算方法

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。空间复杂度不是程序占用了多少字节的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法。

习题

空间复杂度比较常用的有:O(1)、O(n)、O(n²),我们下面来看看:

空间复杂度 O(1)

如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)

int i = 1;
int j = 2;
++i;
j++;
int m = i + j;

代码中的 i、j、m 所分配的空间都不随着处理数据量变化,因此它的空间复杂度 S(n) = O(1)

空间复杂度 O(n)

int[] m = new int[n]
for(i=1; i<=n; ++i)
{
   j = i;
   j++;
}

这段代码中,第一行new了一个数组出来,这个数据占用的大小为n,虽然有循环,但没有再分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,即 S(n) = O(n).

例一

//计算冒泡排序函数的空间复杂度
void BubbleSort(int* a, int N)
{
	assert(a);
	for (int i = 0; i < N; i++)
	{
		int exchange = 0;
		for (int j = 0; j < N - 1 - i; j++)
		{
			if (a[j]>a[j + 1])
			{
				int tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
				exchange = 1;
			}
		}
		if (exchange == 0)
			break;
	}
}

冒泡排序函数中使用了常数个额外空间(即常数个变量),所以用大O的渐进表示法表示冒泡排序函数的空间复杂度为O(1) 。

例二

//计算阶乘递归函数的空间复杂度
long long Factorial(size_t N)
{
	return N < 2 ? N : Factorial(N - 1)*N;
}

阶乘递归函数会依次调用Factorial(N),Factorial(N-1),…,Factorial(2),Factorial(1),开辟了N个空间,所以空间复杂度为O(N) 。

注:递归算法的空间复杂度通常是递归的深度(即递归多少层)。

在这里插入图片描述

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

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

相关文章

桂林电子科技大学计算机工程学院、广西北部湾大学计信学院莅临泰迪智能科技参观交流

5月18日&#xff0c;桂林电子科技大学计算机工程学院副院长刘利民、副书记杨美娜、毕业班辅导员黄秀娟、广西北部湾大学计信学院院长助理刘秀平莅临广东泰迪智能科技股份有限公司产教融合实训基地参观交流。泰迪智能科技副总经理施兴、广西分公司郑廷和、梁霜、培训业务部孙学镂…

Outlook 开启smtp配置

微软 Outlook 邮箱各种服务详细信息 服务类型服务器地址端口加密方法POPoutlook.office365.com995TLSIMAPoutlook.office365.com993TLSSMTPsmtp.office365.com587STARTTLS 然而仅仅有以上信息还不够&#xff0c;需要获取服务密码 (授权码) 才能够使用 POP, IMAP, SMTP 这三种…

常见应用流量特征分析

目录 1.sqlmap 1.常规GET请求 2.通过--os-shell写入shell 3.post请求 2.蚁剑 编码加密后 3.冰蝎 冰蝎_v4.1 冰蝎3.2.1 4.菜刀 5.哥斯拉 1.sqlmap 1.常规GET请求 使用的是sqli-labs的less7 &#xff08;1&#xff09;User-Agent由很明显的sqlmap的标志&#xff0c;展…

基础常用动词,柯桥西班牙语培训

1. Ser&#xff1a;是 表示身份: Soy Ana. Soy estudiante. 我是安娜。我是一名学生。 表示属性: Es duro. 这是硬的。 表示国籍: Soy espaol, de Madrid. 我是西班牙人&#xff0c;来自马德里。 2. Estar: 是..., 在... 表示身体状况: Estoy muy cansada, necesito dormir.我很…

JMH301【亲测】5月最新整理【神鬼传奇】斗罗超变单机版175级新宠物宝宝坐骑丰富超变定制装备带完整GM命令网游单机虚拟机一键端

资源介绍&#xff1a; 是否需要虚拟机&#xff1a;是 文件大小&#xff1a;压缩包约8.6G 支持系统&#xff1a;win7、win10、win11 硬件需求&#xff1a;运行内存8G 4核及以上CPU 下载方式&#xff1a;百度网盘 内容持续更新&#xff01; 资源截图&#xff1a; 下载地址…

DataBinding viewBinding(视图绑定与数据双向绑定)简单案例 (kotlin)

先上效果&#xff1a; 4个view的文字都是通过DataBinding填充的。交互事件&#xff1a;点击图片&#xff0c;切换图片 创建项目&#xff08;android Studio 2023.3.1&#xff09; Build.gradle(:app) 引入依赖库&#xff08;完整源码&#xff09; buildFeatures { vie…

Docker访问文件权限受限问题解决

问题描述 运行项目的docker环境&#xff0c;新添加了一个数据集&#xff0c;但是数据集的访问权限受限&#xff08;Permission dinied&#xff09;&#xff0c;运行的命令如图所示 问题解决 chmod 777 xxx YYDS&#xff01;&#xff01;&#xff01;但是单纯直接运行会因为权限…

产品经理-交互说明撰写(八)

1. 交互说明 交互说明可以看做是交互设计师或者产品经理输出的最核心的”产品“交互说明面向的”用户“是下游的同事 ⇒ UI设计师、开发工程师、测试工程师 2. 基本交互形式 2.1 页面交互 2.2 元素控件交互 3. 交互说明主要包括以下3个维度 3.1 页面流程&#xff08;页面之…

OpenFeign高级用法:缓存、QueryMap、MatrixVariable、CollectionFormat优雅地远程调用

码到三十五 &#xff1a; 个人主页 微服务架构中&#xff0c;服务之间的通信变得尤为关键。OpenFeign&#xff0c;一个声明式的Web服务客户端&#xff0c;使得REST API的调用变得更加简单和优雅。OpenFeign集成了Ribbon和Hystrix&#xff0c;具有负载均衡和容错的能力&#xff…

在 Android 上存档短信:4 种方法的终极指南

概括 无论是个人对话还是专业信件&#xff0c;我们的短信收件箱很快就会因大量线程和对话而变得混乱。为了帮助管理这种过载&#xff0c;许多 Android 用户转向了归档短信这一便捷功能。在本指南中&#xff0c;我们将探讨如何在 Android 设备上存档短信的详细信息&#xff0c;…

Django中使用Celery(通用方案、官方方案)

Django中使用Celery&#xff08;通用方案、官方方案&#xff09; 目录 Django中使用Celery&#xff08;通用方案、官方方案&#xff09;通用方案场景前置准备完整代码 Celery官方方案【1】注册celery配置【2】创建celery文件【3】init注册【4】添加任务【5】启动worker异步任务…

【qt】下拉列表组件

下拉列表组件 一.Combo Box1.可以直接双击编辑下拉内容2.代码初始化下拉内容3.一次性添加多个下拉内容4.下拉框手动编辑5.下拉内容添加附加值6.下拉添加图标7.获取下拉值 二.总结 一.Combo Box 还是老样子&#xff0c;咱们边做边练 目标图&#xff1a; 1.可以直接双击编辑下…

ThreadLocal原理及使用

一、引言 在Java多线程编程中&#xff0c;ThreadLocal是一个非常有用的工具&#xff0c;它提供了一种将对象与线程关联起来的机制&#xff0c;使得每个线程都可以拥有自己独立的对象副本&#xff0c;从而避免了线程安全问题。然而&#xff0c;使用不当会导致内存泄漏问题。 二…

el-input 自动获取焦点

前言&#xff1a; 需求描述&#xff1a;在 Dialog 对话框中 使用 input 组件&#xff1b;当点击按钮&#xff0c;Dialog 对话框显示&#xff0c;且里面的 input 组件要自动获取焦点。因为页面上还存在其他的 input 组件&#xff0c;所以使用 自动获取焦点属性没用&#xff01;&…

AppInventor2要在界面上做一个电量图标,有什么好的思路吗?

问&#xff1a;要在界面上做一个电量图标&#xff0c;有什么好的思路吗&#xff1f; 答&#xff1a;首先&#xff0c;很容易想到使用进度条相关的组件&#xff0c;原生”滑动条“组件可以吗&#xff1f; 答案显而易见&#xff0c;首先它的样式自定义不够&#xff0c;UI不外乎上…

使用Flask Swagger自动生成API文档

文章目录 安装Flask Swagger使用Flask Swagger生成API文档总结1. 自动化文档生成2. 交互式文档展示3. 规范化API设计4. 提升协作效率5. 支持多种格式 Flask Swagger是一种用于管理Flask API文档的工具。它基于OpenAPI规范&#xff0c;可以自动生成API的交互式文档。使用Flask S…

明火炒菜不安全?NO 华火新能源电燃灶“电生明火”安全又环保

明火炒菜&#xff0c;色味俱全&#xff0c;这就是为什么电磁炉&#xff08;无火&#xff09;炒菜不好吃&#xff0c;越来越少人用的主要原因&#xff01; 在中国&#xff0c;明火炒菜这一传统的烹饪方式延绵了几千年&#xff0c;是中华文化传承的瑰宝&#xff0c;早已根深蒂固于…

k8s 部署 CoreDNS master02 节点部署 负载均衡部署

目录 一、部署 CoreDNS 1.1.在所有 node 节点上操作 1.2.在 master01 节点上操作 1.3.DNS 解析测试 二、master02 节点部署 2.1.从 master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点 2.2.修改配置文件kube-apiserver中的IP 2.3.在 …

NegativePrompt:利用心理学通过负面情绪刺激增强大型语言模型

【摘要】大型语言模型 (LLM) 已成为各种应用不可或缺的一部分&#xff0c;从传统的计算任务到高级人工智能 (AI) 应用。这种广泛的应用促使社会科学等各个学科对 LLM 进行了广泛的研究。值得注意的是&#xff0c;研究表明 LLM 具有情商&#xff0c;可以通过积极的情绪刺激进一步…

温故而知新-JUC篇【面试复习】

温故而知新-JUC篇【面试复习】 前言版权推荐温故而知新-JUC篇多线程Java语言中的线程安全线程安全的实现方法线程的创建线程的状态wait和sleep的区别ThreadLocalsynchronize的优化synchronize和Reentrant的对比AQS线程池ThreadPoolExecutorThreadPoolExecutor源码ConcurrentHas…