数据结构开始——时间复杂度和空间复杂度知识点笔记总结

好了,经过了漫长的时间学习c语言语法知识,现在我们到了数据结构的学习。

首先,我们得思考一下

什么是数据结构?

数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。


算法又是什么?

定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果
 

算法讲究效率

如何衡量一个算法的好坏
如,斐波那契数列(虽然代码简单,但是它的效率高吗?)

long long Fib(int n)
{
if(n < 3)
{
  return 1;
}

    return Fib(n-1) + Fib(n-2);
}

是先(黑色)一步一步进去下去,算到Fib(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)
{                                  这里是N^2
++count;
}
}
for (int k = 0; k < 2 * N ; ++ k)
{
++count;                             这里是2*N
}
int M = 10;
while (M--)
{                                     这里是10次
++count;
}

经过计算我们可以得出:是F(N)=N^2+2*N+10

其实,对于求复杂度,我们一般使用大O的渐进表示法,,现在来介绍下:

大O的渐进表示法

1.大O符号:是用于描述函数渐进行为的数学符号

2.规则方法:

1)用常数1取代运行时间中的所有加法常数。

2)、在修改后的运行次数函数中,只保留最高阶项

3)、如果最高阶项存在且不是1,则去除与这个项目相乘的常数

最后得到的结果就是大O阶

eg:N(10000000000000)这应该写成什么呢?

答案:仍然是O(1).

有人会问为啥它这个数那么大了,还是用O(1)表示呢?

现在我们来用形象的例子来解释下:

假如那里有座泰山,我们要铲平,
不同视角:会不同
我们人的视角觉得它非常大,
但是放到太阳系里面,就显得非常小了。

同样,对于编程也是一样的道理。

通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数

另外有些算法的时间复杂度存在最好、平均和最坏情况:

最坏情况:任意输入规模的最大运行次数(上界)平均情况:任意输入规模的期望运行次数

最好情况:任意输入规模的最小运行次数(下界)例如:在一个长度为N数组中搜索一个数据x

最好情况:1次找到最坏情况:N次找到平均情况:N/2次找到

所以,我们实际中一般关注的是最坏的情况。

原因:同样是以一个形象的例子来解释

约会的预期管理
情人节约会可能到时的时间
最好:17:00
平均:18:00
最坏:19:00
那么因为只有30%的机会准时到
所以是不是选择说19:00时最好,把预期拉到最低。

常见时间复杂度计算举例

void Func2(int N)
{
int count = 0;
for (int k = 0; k < 2 * N ; ++ k)
{                                     这里是2*N次
++count;
}
int M = 10;
while (M--)                          这里是10次
{
++count;
}
printf("%d\n", count);
}

所以,函数是不是就是:F(N)=2*N+10

根据大O法:得时间复杂度就是O(N)

例子2:

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

函数式:F(N)=M+N

注意:这里的M,N都是未知数,并不是具体数

所以根据大O法:时间复杂度O(M+N)
 

例子3:

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

函数式:F(N)=100

根据大O法:由于它是常数嘛,所以用1代替

所以时间复杂度:O(1).

例子4:

const char * strchr ( const char * str, int character );

对于指针,如果没有具体说,一般默认都是O(N)

例子5:

void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
 {                                        一般没说的话,默认N次
   int exchange = 0;
   for (size_t i = 1; i < end; ++i)          因为两个for循环,所以是N^2次
   {
     if (a[i-1] > a[i])
     {
       Swap(&a[i-1], &a[i]);
       exchange = 1;
     }
   }
  if (exchange == 0)              因为这里有了判断,它可以改变最好的情况
  break;                          如果没有这句,
 }                                最好也是O(N^2)
                                  因为它无法知道它已经排序了  
 }                                
 

排序

最好(已经排序好大小):O(1)  X有人说是看一眼就知道它的大小排序了,但是你一亿的时候呢,你并不知道其他数字2与这个的大小?

 你是不是也是要一个一个对比下去呢?
所以  时间复杂度: O(N)  √   

最坏:O(N^2)
其实这里不敢数循环,因为以后会学更复杂的
N-1 N-2 N-3....3 2 1  等差数列 算出O(N^2)

例子5:我们之前写过的二分查找

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

 

          四    第三次             第二次                     第一次 

 我们可以发现,这是不是一次查找,我们就可以筛选掉一半。

最坏情况:区间缩放到一个值时,要么找到,要么找不到
假设N是数组个数,x是最坏查找次数
N/2/2/2/2.../2=1
折半查找多少次就除多少个2
假设是x次

2^x=N
x=log N 

这里我们先来说明一下:

接着,我们来看一下二分查找的显著优势:

对比:

N         1000    100W    10亿                  2^10=1024

O(N)      1000    100W   10亿                 2^20=1024*1024

O(log N)  10       20         30                     2^30=1024*1024*1024  

我们可以看到这二分查找极大改变它的时间效率。

但是一个很不友好的一点是,它仅仅局限于排序好的数,所以我们以后也不太实用

 例子6:

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

 这是不是相当于有N+1次,O(N+1)

根据大O法:时间复杂度:O(N)

Fac(N)
Fac(N-1)
Fac(N-2)
....
Fac(1)    
Fac(0)       

例子七:

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

 等比数列 -缺失(常数)

时间:O(2^N)
空间:O(N)

对此,我们可以得出来:

时间一去不复返,不可重复利用
空间用了以后要归还,可以重复利用。

空间复杂度

1.空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度
2.空间复杂度算的是变量的个数(而不是程序占用了多少bytes的空间,因为这个也没太大意义)

注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显示申请的额外空间来确定。

3.空间复杂度的使用规则也是:大O法

空间复杂度举例:

例子1:

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

我们上面说了空间复杂度算的是变量的个数

我们看到了上面用了三个变量:end,exchange,i。 -->O(3)

根据大O法:O(1).

例子2:绝大多数空间复杂度都是O(1)或O(N)

 计算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;                        为什么要多加1,因为数组从0开始,
   fibArray[1] = 1; 
   for (int i = 2; i <= n ; ++i)
   {
      fibArray[i] = fibArray[i - 1] + fibArray [i - 2];
   }
   return fibArray;
}

上面创建了n+1个空间

所以根据大O法:O(N)

例子3:

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

 值得注意的是

递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间

函数在栈的开辟函数栈帧时是单独开辟的。调用本身时,会再2开辟一块空间作为新的函数栈帧,但是在此外并没有创建额外的变量,所以会认为创建的每一块栈帧空间复杂度变量是常数个。

举个形象例子:

空间销毁是把那个使用权还给操作系统了,并不是说这块空间就没了
内存的申请,就相当于 住酒店一样,当这房间不用了,这不是说把它炸

所以参数从N到0,共递归了N+1次,

根据大O法:O(N)

例子6:

同样,斐波那契数列也是一样。

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

 空间销毁是把那个使用权还给操作系统了,我们上面说过空间是可以重复使用的,

调用某个函数结束后,再次调用此函数,所用的空间与上一次的函数空间是同一个。

所以,同样是递归了N-1次

由大O法:O(N)。

大O的常见的变化表

祝福语:

最后的最后,希望我们都能战胜困难,一步一步地坚持下去,为以后拿到好offer!

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

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

相关文章

Linux USB开发整理和随笔

目录 1 概述 2 硬件原理基础 2.1 USB发展 2.2 USB的拓扑 2.3 硬件接口 2.4 USB总线协议 2.4.1 通信过程 2.4.2 概念关系 2.4.3 管道PIPE 2.4.4 传输 2.4.5 事务 2.4.6 包结构与类型 2.4.6.1 令牌包 2.4.6.2 数据包 2.4.6.3 握手包 2.5 描述符 2.5.1 设备描述符…

一键找出图像中物体的角点

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

考研数学【线性代数基础box(数二)】

本文是对数学二线性代数基础进行总结&#xff0c;一些及极其简单的被省略了&#xff0c;代数的概念稀碎&#xff0c;不如高数关联性高&#xff0c;所以本文仅供参考&#xff0c;做题请从中筛选&#xff01; 本文为初稿&#xff0c;后面会根据刷题和自己的理解继续更新 第一章…

警惕!手动调整服务器时间可能引发的系统灾难

警惕&#xff01;手动调整服务器时间可能引发的系统灾难 1. 鉴权机制1.1 基于时间戳的签名验证1.2 基于会话的认证机制&#xff08;JWT、TOTP&#xff09; 2. 雪花算法生成 ID 的影响2.1 时间戳回拨导致 ID 冲突2.2 ID 顺序被打乱 3. 日志记录与审计3.1 日志顺序错误3.2 审计日…

【Linux】Systemtap在CentsOS9上测试成功了

在Ubuntu上测试没有成功&#xff0c;先看看运行成功的效果吧&#xff1a; 看到运行的效果&#xff0c;可以安心些&#xff0c;哈哈 指导操作来源于这里&#xff1a;SystemTap 主要来源于这里&#xff1a; https://sourceware.org/systemtap/SystemTap_Beginners_Guide/using-s…

【EthIf-03】 EthernetInterface软件栈的文件组织结构

上图为《AUTOSAR_SWS_EthernetInterface【v2.2.0 】》给出的EthernetInterface软件栈的文件组织结构,本文主要关注arccore代码中已存在的文件的功能和作用,不知道的小伙伴可以查看🔗EthIf的文件结构中的src和inc目录下的文件有哪些: 1. 文件结构 1.1 EthIf_Cbk.h 头文…

【LeetCode刷题之路】622.设计循环队列

LeetCode刷题记录 &#x1f310; 我的博客主页&#xff1a;iiiiiankor&#x1f3af; 如果你觉得我的内容对你有帮助&#xff0c;不妨点个赞&#x1f44d;、留个评论✍&#xff0c;或者收藏⭐&#xff0c;让我们一起进步&#xff01;&#x1f4dd; 专栏系列&#xff1a;LeetCode…

基于windows环境使用nvm安装多版本nodejs

目录 前言 一、卸载node 二、nvm是什么&#xff1f; 三、nvm安装 1.官网下载 nvm 包 2. 安装nvm-setup.exe 3. 配置路径和下载镜像 4. 检查安装是否完成 四、 使用nvm安装node 五、修改npm默认镜像源为淘宝镜像 六、环境变量配置 1. 新建目录 2. 设置环境变量 七…

Neo4j+Neovis+Vue3:前端连接数据库渲染

Neovis&#xff08;github&#xff09;&#xff1a;https://github.com/neo4j-contrib/neovis.js Neovis配置文档&#xff1a;neovis.js (neo4j-contrib.github.io) 一、安装Neo4j 参考文章&#xff1a;neo4j下载安装配置步骤-CSDN博客 二、Neovis使用 1.npm引入 ?npm ins…

《宇宙机器人》提示错误弹窗“找不到d3dx9_43.dll”是什么原因?“d3dx9_43.dll缺失”怎么解决?

电脑游戏运行时常见问题解析&#xff1a;《宇宙机器人》提示“找不到d3dx9_43.dll”的解决之道 TGA2024落幕&#xff0c;年度最佳游戏——《宇宙机器人》&#xff0c;作为一名在软件开发领域深耕多年的从业者&#xff0c;我深知电脑游戏在运行过程中可能会遇到的各种挑战&…

Cesium 限制相机倾斜角(pitch)滑动范围

1.效果 2.思路 在项目开发的时候&#xff0c;有一个需求是限制相机倾斜角&#xff0c;也就是鼠标中键调整视图俯角时&#xff0c;不能过大&#xff0c;一般 pitch 角度范围在 0 至 -90之间&#xff0c;-90刚好为正俯视。 在网上查阅了很多资料&#xff0c;发现并没有一个合适的…

28. Three.js案例-创建圆角矩形并进行拉伸

28. Three.js案例-创建圆角矩形并进行拉伸 实现效果 知识点 WebGLRenderer (WebGL渲染器) WebGLRenderer 是 Three.js 中用于渲染 3D 场景的主要渲染器。 构造器 WebGLRenderer( parameters : Object ) 参数类型描述parametersObject渲染器的配置参数&#xff0c;可选。 …

transformer学习笔记-自注意力机制(2)

经过上一篇transformer学习笔记-自注意力机制&#xff08;1&#xff09;原理学习&#xff0c;这一篇对其中的几个关键知识点代码演示&#xff1a; 1、整体qkv注意力计算 先来个最简单未经变换的QKV处理&#xff1a; import torch Q torch.tensor([[3.0, 3.0,0.0],[0.5, 4…

基于米尔全志T527开发板的OpenCV进行手势识别方案

本文将介绍基于米尔电子MYD-LT527开发板&#xff08;米尔基于全志T527开发板&#xff09;的OpenCV手势识别方案测试。 摘自优秀创作者-小火苗 米尔基于全志T527开发板 一、软件环境安装 1.安装OpenCV sudo apt-get install libopencv-dev python3-opencv 2.安装pip sudo apt…

arXiv-2024 | VLM-GroNav: 基于物理对齐映射视觉语言模型的户外环境机器人导航

作者&#xff1a; Mohamed Elnoor, Kasun Weerakoon, Gershom Seneviratne, Ruiqi Xian, Tianrui Guan, Mohamed Khalid M Jaffar, Vignesh Rajagopal, and Dinesh Manocha单位&#xff1a;马里兰大学学院公园分校原文链接&#xff1a;VLM-GroNav: Robot Navigation Using Phys…

Typora 修改默认的高亮颜色

shift F12 参考 怎么给typora添加颜色&#xff1f;

基于阿里云Ubuntu22.04 64位服务器Java及MySql环境配置命令记录

基于阿里云Ubuntu22.04 64位服务器Java及MySql环境配置命令记录 Java 23 离线环境配置MySql 环境配置MySQL常用命令 Java 23 离线环境配置 下载 Ubuntu环境下 Java 23 离线包 链接: java Downloads. 在Linux环境下创建一个安装目录 mkdir -p /usr/local/java将下载好的jdk压缩…

【树莓派4B】MindSpore lite 部署demo

一个demo&#xff0c;mindspore lite 部署在树莓派4B ubuntu22.04中&#xff0c;为后续操作开个门&#xff01; 环境 开发环境&#xff1a;wsl-ubuntu22.04分发版部署环境&#xff1a;树莓派4B&#xff0c;操作系统为ubuntu22.04mindspore lite版本&#xff1a;mindspore-li…

RK3576 Android14,内存大于4G时UVC应用无法申请内存

最近有个项目需要将Linux虚拟成UVC摄像头&#xff0c;开发过程中遇到一个奇怪的事情&#xff0c;通过V4l2框架接口申请内存时&#xff0c;相同的板子&#xff0c;只是内存一个4G一个8G。4G的内存可以申请成功&#xff0c;8G就不行。提示“内存不足” 内存更大反而内存不足&…

HarmonyOS-高级(四)

文章目录 应用开发安全应用DFX能力介绍HiLog使用指导HiAppEvent &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;HarmonyOS专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月11日11点18分 应用开发安全 应用隐私保护 隐私声明弹窗的作…