数据结构与算法-时间复杂度与空间复杂度
数据结构与算法
- 🎈1.概论
- 🔭1.1什么是数据结构?
- 🔭1.2什么是算法?
- 🎈2.算法效率
- 🔭2.1如何衡量一个算法的好坏?
- 🔭2.2算法的复杂度
- 🔭2.3时间复杂度
- 📖2.3.1时间复杂度的概念
- 📖2.3.2大O的渐进表达式
- 📖2.3.3常见时间复杂度计算举例
- 🔭2.4空间复杂度
- 🔭2.5常见复杂度对比
🎈1.概论
🔭1.1什么是数据结构?
数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。
🔭1.2什么是算法?
算法就是定义良好的计算过程,他取一个或一组的值为输入,并产生一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。
🎈2.算法效率
🔭2.1如何衡量一个算法的好坏?
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
🔭2.2算法的复杂度
时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。 在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
🔭2.3时间复杂度
📖2.3.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;}printf("%d\n", count);
}
- N = 10 F(N) = 130
- N = 100 F(N) = 10210
- N = 1000 F(N) = 1002010
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
📖2.3.2大O的渐进表达式
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法:
- 用常数1取代运行时间中的所有加法常数。
- 在修改后的运行次数函数中,只保留最高阶项。
- 如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为:O(N2)
- N = 10 F(N) = 100
- N = 100 F(N) = 10000
- N = 1000 F(N) = 1000000
通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
📖2.3.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);
}
使用大O的渐进表示法以后,Func2的时间复杂度为:O(N)
✅示例三:
// 计算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);
}
使用大O的渐进表示法以后,Func3的时间复杂度为:O(M+N)
✅示例四:
// 计算Func4的时间复杂度?
void Func4(int N)
{int count = 0;for (int k = 0; k < 100; ++k){++count;}printf("%d\n", count);
}
使用大O的渐进表示法以后,Func4的时间复杂度为:O(1)
✅示例五:
// 计算strchr的时间复杂度?
const char * strchr ( const char * str, int character );
本函数是用来在一个字符串中找出某个字符的,那么假设我们这里的字符串是
hello world
。
如果我们需要查找的是h
,那么我们只需要查找1
次,这也称为最好情况,即任意输入规模的最小运行次数。
如果我们需要查找的是w
,那么我们只需要查找N/2
次,这也称为平均情况,即任意输入规模的期望运行次数。
如果我们需要查找的是d
,那么我们只需要查找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;}
}
使用大O的渐进表示法以后,Func6的时间复杂度为:O(N2)
✅示例七:
// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n - 1;// [begin, end]:begin和end是左闭右闭区间,因此有=号while (begin <= end){int mid = begin + ((end - begin) >> 1);if (a[mid] < x)begin = mid + 1;else if (a[mid] > x)end = mid - 1;elsereturn mid;}return -1;
}
使用大O的渐进表示法以后,Func7的时间复杂度为:O(logN)
✅示例八:
// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2);
}
使用大O的渐进表示法以后,Func8的时间复杂度为:O(2N)
✅示例九:
// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
if(0 == N)
return 1;
return Fac(N-1)*N;
}
使用大O的渐进表示法以后,Func9的时间复杂度为:O(N)
🔭2.4空间复杂度
空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 。
空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。
空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
✅示例1:
// 计算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;}
}
使用大O的渐进表示法以后,示例1的空间复杂度为:O(1)
✅示例2:
// 计算Fibonacci的空间复杂度?
// 返回斐波那契数列的前n项
long long* Fibonacci(size_t n)
{if (n == 0)return NULL;long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n; ++i){fibArray[i] = fibArray[i - 1] + fibArray[i - 2];}return fibArray;
}
使用大O的渐进表示法以后,示例2的空间复杂度为:O(N)
✅示例3:
// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N)
{if (N == 0)return 1;return Fac(N - 1) * N;
}
使用大O的渐进表示法以后,示例3的空间复杂度为:O(N)
✅示例4:
// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2);
}
使用大O的渐进表示法以后,示例4的空间复杂度为:O(N)
空间是可以重复利用的,不累计的;时间是一去不复返的,累计的。
🔭2.5常见复杂度对比
执行次数函数 | 阶 | 非正式术语 |
---|---|---|
3 | O(1) | 常数阶 |
2n+1 | O(n) | 线性阶 |
3n2+2n+1 | O(n2) | 平方阶 |
3log2n(2为底数)+2 | O(logn) | 对数阶 |
n+4nlog2n(2为底数)+7 | O(nlogn) | nlogn阶 |
5n3+3n2+2n+1 | O(n3) | 立方阶 |
2n | O(2n) | 指数阶 |
常用时间复杂度所消耗时间从小到大依次是:O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
好啦,关于复杂度的知识点到这里就结束啦,后期会继续更新数据结构与算法的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️
相关文章:

数据结构与算法-时间复杂度与空间复杂度
数据结构与算法 🎈1.概论🔭1.1什么是数据结构?🔭1.2什么是算法? 🎈2.算法效率🔭2.1如何衡量一个算法的好坏?🔭2.2算法的复杂度🔭2.3时间复杂度📖2…...
数组的去重
根据您提供的代码片段,看起来您尝试使用嵌套的 for 循环将数组 data 中的元素添加到新数组 newData 中。然而,在您给出的代码中,if 语句的条件部分为空,可能是因为您还没有确定用于判断重复项的条件。如果您想要去除数组中的重复项…...

Electron自动化测试技术选型调研
Electron简介 Electron是一个开源的框架,用于构建跨平台的桌面应用程序。它由GitHub开发并于2013年首次发布。Electron允许开发人员使用Web技术(如HTML、CSS和JavaScript)来构建桌面应用程序,同时可以在Windows、macOS和Linux等操…...

微服务学习(九):安装OpenOffice
微服务学习(九):安装OpenOffice 一、下载OpenOffice 下载地址:OpenOffice 二、开始安装 上传资源到服务器 解压资源包 tar -zxvf Apache_OpenOffice_4.1.13_Linux_x86-64_install-rpm_zh-CN.tar.gz进入zh-CN/RPMS目录下安装…...

SAP Oracle表空间扩展技术手册
1、DBACOCKPIT下查看表空间 当表空间不足(达到99%)时,需要按以下步骤扩充表空间(每次扩充20000M,20G): (也可以通过DB13,DB02查看表空间) 新浪博客 Tablespace PSAPSR3 is 100% used | SAP Community Oracle是通过增加数据文件的方式来为表空间扩容。为指定表空间增…...
Linux系统编程——线程的学习
学习参考博文: Linux多线程编程初探 Linux系统编程学习相关博文 Linux系统编程——文件编程的学习Linux系统编程——进程的学习Linux系统编程——进程间通信的学习Linux系统编程——网络编程的学习 Linux系统编程——线程的学习 一、概述1. 进程与线程的区别2. 使…...

zemaxMIF曲线图
调制传递函数( Modulation Transfer Function,MTF )是用来形容光学系统成像质量的重要指标。 通过对光学系统像空间进行傅里叶变换,可以得到一张分析图表,来描述像面上对比度和空间频率之间的对应关系。 对比度&…...

【苹果】SpringBoot监听Iphone15邮件提醒,Selenium+Python自动化抢购脚本
前言 🍊缘由 Iphone15来了,两年之约你还记得吗? 两年前,与特别的人有一个特别的约定。虽物是人非,但思念仍在。 遂整合之前iphone13及iphone14的相关抢购代码,完成一个SpringBoot监听Iphone15有货邮件提…...

什么是WhatsApp群发,WhatsApp协议,WhatsApp云控
那么WhatsApp群控云控可以做什么呢? 1、获客 自动化引流,强大的可控性,产品快速拓客 2、导流 一键式傻瓜化自动加好友,群发,朋友圈营销 3、群控 一键式拉群好友,建群,进群 …...

RealVNC viewer 窗口指定默认显示
RealVNC Viewer关于显示器(monitor)的参数有两个,一个是monitor,一个是useallmonitor。 monitor就是指定viewer窗体在哪个显示器上显示的,windows下的默认值是空白,改为\\.\DISPLAY2 就可以在打开远程窗口的时候默认在副屏上显…...
图论20(Leetcode1254.统计封闭岛屿的数目)
代码: class Solution {static int[][] dirs {{1,0},{-1,0},{0,1},{0,-1}};public int closedIsland(int[][] grid) {int num 0; for(int i0;i<grid.length;i){for(int j0;j<grid[0].length;j){if(grid[i][j]0){int[] start {i,j};if(getIsland(start,gri…...
Docker 的基本概念和优势,以及在应用程序开发中的实际应用
Docker是一种开源的容器化平台,它可以将应用程序打包成容器,并且可以在不同的环境中运行。Docker的基本概念包括: 镜像(Image):Docker镜像是一个可执行的包,它包含了运行应用程序所需的所有文件…...

数据仓库整理
数仓 olap vs oltp OLTP主要用于支持日常的业务操作,如银行交易、电子商务等,强调数据的准确性、实时性和并发性。OLAP主要用于支持复杂的数据分析,如数据仓库、决策支持等,强调数据的维度、聚合和可视化。 将OLTP数据库的数据…...

《C++API设计》读书笔记(3):模式
本章内容 本章涵盖了一些与CAPI设计相关的设计模式和惯用法。 “设计模式(Design Pattern)”表示软件设计问题的一些通用解决方案。该术语来源于《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Softwar…...
小程序搜索词优化:小陈运营的秘密武器
大家好,我是小陈,今天要和大家分享一下小程序搜索词优化的经验和技巧。在数字化时代,小程序已经成为许多企业的重要工具,但要让小程序在竞争激烈的市场中脱颖而出,搜索词优化是不可或缺的一环。在本文中,我…...

SpringSecurity 入门
文章目录 Spring Security概念快速入门案例环境准备Spring配置文件SpringMVC配置文件log4j配置文件web.xmlTomcat插件 整合SpringSecurity 认证操作自定义登录页面关闭CSRF拦截数据库认证加密认证状态记住我授权注解使用标签使用 Spring Security概念 Spring Security是Spring…...
【每日一题Day335】LC1993树上的操作 | dfs
树上的操作【LC1993】 给你一棵 n 个节点的树,编号从 0 到 n - 1 ,以父节点数组 parent 的形式给出,其中 parent[i] 是第 i 个节点的父节点。树的根节点为 0 号节点,所以 parent[0] -1 ,因为它没有父节点。你想要设计…...

FPGA:卷积编码及维特比译码仿真
FPGA:卷积编码及维特比译码仿真 本篇记录一下在FPGA中完成卷积编码和维特比译码的过程,通过代码解释编码的过程和译码的过程,便于理解,同时也方便移植到其他工程中。 1. 准备工作 卷积编译码IP核—convolutionIP核和viterbiIP核…...

MySQL学习笔记4
客户端工具的使用: MySQL: mysql命令行工具,一般用来连接访问mysql的数据。 案例:使用mysql客户端工具连接服务器端(用户名:root;密码:123456). [rootmysql-server ~]#…...
JavaFX:窗体显示状态,模态非模态
程序窗体显示一般有3中模式。非模态和模态,其中模态又分为程序模态和窗体模态。 非模态可以理解为窗体之间没有任何限制,可以用鼠标、键盘等工具在窗体间切换。 程序模态是窗体打开后,该程序的所有窗体都被冻结,无法切换&#x…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...
stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...