【数据结构初阶】时间复杂度和空间复杂度详解

news2024/12/24 21:42:34

今天我们来详细讲讲时间复杂度和空间复杂度,途中如果有不懂的地方可翻阅我之前文章。

个人主页:小八哥向前冲~-CSDN博客

数据结构专栏:数据结构【c语言版】_小八哥向前冲~的博客-CSDN博客

c语言专栏:c语言_小八哥向前冲~的博客-CSDN博客

 在平常写代码时,碰见一个问题,有时候第一种思路代码量相对较多,而第二种思路代码量相对较小。这时候你可能会选择代码量较小的思路进行解答。但真的代码量越少,代码运行效率更快嘛?

那可不一定,有时候代码量大的反而更好,算法效率并不取决于代码量的,衡量一个算法或一个思路好不好,主要看的是时间复杂度和空间复杂度的

时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间

我们率先讲讲时间复杂度。

时间复杂度概念

我们先来看看它的定义:

在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一 个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知 道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个 分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。

也就是说:算法中基本操作的执行次数就是时间复杂度

我们来看个例子:

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

要计算它的时间复杂度,我们不妨计算count执行了多少次,显然执行了N*N+2*N+10次,到这里你不会就以为它的空间复杂度就是N*N+2*N+10了吧。那可就大错特错了!

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

大o的渐进表示法

这里我们不妨看图:

不难看出F(N)的值主要取决于N*N,那么我们说这个算法的时间就是o(N*N),也就是说我们只取对这个算法影响最深的一项

也就是说大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。

但是有时候我们的算法会出现最好情况,最坏情况。什么意思呢?我们看个例子(二分查找):

 // 计算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;
        else
            return mid;
    }
 
    return -1;
 }

这个例子的最坏情况:一次就找到。最坏情况:log2N次。为什么呢?我们分析一下:查找一次对半砍,两次对半砍两次,一直到砍到只剩最后一个值了或者最后一个值都不是要找的数,这就是最坏情况。

我们计算一下:

注意:如果有多种情况的话,我们一般算最坏情况。

我们来看看其他例子。

计算时间复杂度例题

冒泡排序例子

// 计算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次冒泡,依次递减,其中每趟冒泡两两比较,我们不难算出N-1+N-2+N-3+N-4+........+1,也就是等差数列,我们算出为N*(N-1)/2,到这里是不是豁然开朗?最终为o(N*N)

常数例子

我们再来看一下另一个常数例子:

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

我们不难看出执行了100次(非常准确),但不会你以为时间复杂度为o(100)吧?其实不然,确实执行行了100次,但因为是常数次,我们一律规定为o(1)。

注意:这里的o(1)并不是只执行了1次,而是代表执行了常数次!

递归例子

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

刚刚接触递归例子是不是有点摸不着头脑?别急!

我们知道当N为0时就停止,当N>0时就一直调用这个函数,调用多少次呢?调用到0就停止!不难算出调用了N次,时间复杂度也就是o(N)!

我们可以上图理解一下:

我们来看一个另一个典型例子----斐波拉及数列!

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

我们不难看出:

F(N)调用F(N-1)和F(N-2),F(N-1)调用F(N-2)和F(N-3)........直到调用到N<3就停止

既然这样仍然看不出执行次数,我们上图看看:

这样看是不是更加清楚呢?但是仍然存在一些瑕疵和疏漏:有些项并没有那么多项

我们再上图:

值得注意的是不影响算时间复杂度!

显然这个递归算法不实用!因为次数一旦大一点,计算机就算不出来(要耗费一点时间,不信可以自行试试!)

空间复杂度概念

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

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

一般理解了时间复杂度,空间的复杂度就手到擒来了!

我们来看一些例题感受一下!

计算空间复杂度例题

常数例子

一个最常见的常数例子就是冒泡排序了,我们来看看:

// 计算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)

常见例子

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;

不难看出:开辟了n+1个额外空间,也就是o(N)

递归例子

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

不难看出:递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。空间复杂度为O(N)

常见复杂度对比

算法有很多种,只要存在就有它的道理----存在即合理!只要我们理解它的底层逻辑,那么什么都不在话下!

好了,我们下期见!

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

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

相关文章

OceanBase 助力同方智慧能源,打造安全可靠、高性能的能源数据架构

本文作者&#xff1a;丁泽斌&#xff0c;同方智慧能源数据库工程师 业务背景 作为同方股份有限公司旗下的领军企业&#xff0c;同方智慧能源集团矢志成为全球领先的综合智慧能源解决方案提供商。凭借中核集团和清华大学的科技实力&#xff0c;专注于向建筑、交通、工业、北方供…

Linux工具篇 之 vim概念 操作 及基础指令讲解

学校不大 创造神话 讲桌两旁 陨落的王 临时抱佛脚 佛踹我一脚 书山有路勤为径 游戏玩的很起劲 想要计算机学的好&#xff0c;我的博客列表是个宝 –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–❀–❀–❀–❀–❀–❀…

linux的lcd屏幕调试

x2600-lcd的sat101cp50d24b1屏幕的驱动调试 1.硬件关联 屏幕型号&#xff1a;sat101cp50d24b1 原理图&#xff1a; 很显然&#xff0c;这是RGB666显示格式的屏幕&#xff0c;RGB管脚DATA0-DATA17--为数据线 DEN 数据使能线。 VSYNC 垂直同步信号线。 HSYNC 水平同步信号线。…

vue-print-nb插件来实现打印功能——打印布局及尺寸处理

之前写过一篇文章是关于vue-print-nb插件实现打印功能&#xff0c; vue插件——vue-print-nb 实现打印功能:http://t.csdnimg.cn/ahuxp 但是在实际使用过程中&#xff0c;打印的效果不尽如人意。下面把打印页面和遇到的问题做一下汇总&#xff1a; 1.html代码——给打印元素绑…

vivado Aurora 8B/10B IP核(6)-本地流量控制(Native Flow Control)

Aurora 8B/10B 协议包括本地流控制&#xff08;NFC&#xff09;接口&#xff0c;其允许接收机通过指定必须 放入数据流的空闲数据跳数来控制接收数据的速率。 甚至可以通过请求发送器临时发送空闲&#xff08;XOFF&#xff09; 来完全关闭数据流.NFC 通常用于防止 FIFO 溢出条…

Python | Leetcode Python题解之第52题N皇后II

题目&#xff1a; 题解&#xff1a; class Solution:def totalNQueens(self, n: int) -> int:def backtrack(row: int) -> int:if row n:return 1else:count 0for i in range(n):if i in columns or row - i in diagonal1 or row i in diagonal2:continuecolumns.add…

【Unity基础】TextMeshPro组件学习过程记录

目录 1.TextMeshPro组件渲染创建文本RTL Editor字体Font Asset字体加粗&#xff0c;下划线等字体大小控制字体颜色控制字体渐变控制字符间隔、单词间隔、行间距、段落间距控制WrappingUV映射控制代码 2.TextMeshPro组件AssetFace InfoGeneration Setting 3.使用Dynamic SDF Sys…

Java基础_JDBC

JDBC 概述步骤项目创建流程代码改进 使用Statement的问题&#xff1a;SQL注入&#xff08;1&#xff09;SQL注入&#xff08;2&#xff09;PreparedStatement1、防止SQL注入2、批处理 事务连接池建立数据库连接实现 日志 概述 Java数据库连接&#xff0c;&#xff08;Java Dat…

机器学习:驱动现代交通运输革命的AI智慧引擎

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

POCEXP编写—多线程

POC&EXP编写—多线程 1. 前言2. 多进程&多线程2.1. 多进程2.1.1. 案例 2.2. 多线程2.2.1. 案例&#xff1a; 2.3. POC的案例&#xff08;模板&#xff09; 3. UA头设置3.1. 随机UA头3.1.1. 案例3.1.2. 模板拼接 4. 代理Proxy4.1. 单代理案例4.2. 多代理案例4.2.1. 请求…

2024年最新linux安装harbor

linux安装harbor Harbor官方介绍这里就不照搬了&#xff0c;说直白点&#xff1a;Harbor就是私有的 Docker Hob 镜像仓库。 前置条件&#xff1a;安装好docker,docker-compose 1、安装harbor离线包&#xff08;在线安装形式不稳定&#xff0c;由于网络原因中间可能中断&…

C++ 小游戏:战斗之旅

一、游戏名称&#xff1a;战斗之旅 游戏规则 角色选择&#xff1a;玩家可以选择不同的角色&#xff0c;每个角色都有不同的属性和技能。商城&#xff1a;玩家可以访问商城购买不同的装备&#xff0c;包括武器和回复物品。战斗&#xff1a;玩家可以与其他角色进行战斗。在战斗…

盲人定位设备:为视障人士独立出行铺设智慧之路

在快速发展的数字时代&#xff0c;科技的每一次跃进都在悄然改变我们的生活方式。对于盲人朋友而言&#xff0c;一款名为“蝙蝠避障”集实时避障于一身的盲人定位设备&#xff0c;正成为他们探索世界、实现独立出行的有力助手。这款设备&#xff0c;不仅重新定义了无障碍出行的…

YOLOv8+PyQt5输电线路缺陷检测(目前最全面的类别检测,可以从图像、视频和摄像头三种路径检测)

1.效果视频&#xff1a;YOLOv8PyQt5输电线路缺陷检测&#xff08;目前最全面的类别检测&#xff0c;可以从图像、视频和摄像头三种路径检测&#xff09;_哔哩哔哩_bilibili 资源包含可视化的输电线路缺陷检测系统&#xff0c;可识别图片和视频当中出现的五类常见的输电线路缺陷…

新书速览|ChatGLM3大模型本地化部署、应用开发与微调

实战文本生成、智能问答、信息抽取、财务预警应用开发&#xff0c;掌握ChatGLM3大模型部署、开发与微调技术 01 本书内容 《ChatGLM3大模型本地化部署、应用开发与微调》作为《PyTorch 2.0深度学习从零开始学》的姊妹篇&#xff0c;专注于大模型的本地化部署、应用开发以及微…

Linux基本指令(3)

目录 时间相关的指令&#xff1a; 1.在显示方面&#xff0c;使用者可以设定欲显示的格式&#xff0c;格式设定为一个加好后接数个标记&#xff0c;其中常用的标记列表如下&#xff1a; 2.在设定时间方面&#xff1a; 3.时间戳&#xff1a; Cal指令&#xff1a; find指令&a…

Kubernetes 声明式语言 YAML

什么是 YAML YAML&#xff08;YAML Ain’t Markup Language&#xff09;是一种可读的数据序列化语言&#xff0c;通常用于配置文件、数据序列化和交换格式。YAML 的设计目标是易读易写&#xff0c;并且能够映射到动态语言中的数据结构 YA加粗样式ML 是 JSON 的超集&#xff0…

纯血鸿蒙APP实战开发——Navigation实现多设备适配案例

介绍 在应用开发时&#xff0c;一个应用需要适配多终端的设备&#xff0c;使用Navigation的mode属性来实现一套代码&#xff0c;多终端适配。 效果图预览 使用说明 将程序运行在折叠屏手机或者平板上观看适配效果。 实现思路 本例涉及的关键特性和实现方案如下&#xff1a…

MyBatis(注解方式操作)

文章目录 1.注解方式操作文件目录1.快速入门&#xff08;完整步骤&#xff09;1.pom.xml&#xff08;完整&#xff09;2.resources/jdbc.properties外部配置文件&#xff08;根据实际情况修改参数&#xff09;3.在resources/mybatis-config.xml&#xff08;完整&#xff09;中配…

仓库管理系统(WMS)是什么?有哪些功能?

阅读本文&#xff0c;你将了解&#xff1a;1、仓库管理&#xff08;WMS&#xff09;是什么&#xff1f; 2、仓库管理系统&#xff08;WMS&#xff09;有什么功能 3、使用仓库管理系统能给企业带来什么好处 一、仓库管理系统是什么 WMS&#xff0c;全称Warehouse Management S…