【数据结构与算法】时间复杂度与空间复杂度

news2024/9/27 15:35:41

目录

一.前言

二.时间复杂度

1.概念

二.大O的渐进表示法

概念:

总结:

三.常见时间复杂度计算举例

例1

例2

例3

例4

例5.计算冒泡排序的时间复杂度

例6.二分算法的时间复杂度

例7.阶乘递归Fac的时间复杂度

例8.斐波那契递归的时间复杂度

四.常见时间复杂度对比

 五.空间复杂度

概念

例1

例2

例3


一.前言

从这篇文章开始,C语言的学习就结束了,接下来将会开启数据结构与算法的学习。

早期,计算机刚被发明出来,内存空间并不是很大,所以不仅追求程序运行时的时间效率,还追求空间效率,但发展到今天,已经不太追求空间效率了,时间效率的追求是不变的。

下面就让我们一起学习时间复杂度和空间复杂度是什么吧~

二.时间复杂度

1.概念

1.时间复杂度是一个函数(注意这不是编程语言里的函数,而是数学意义上的函数)

2.这个函数指的是算法跑的次数的函数,并不是算法运行的时间,因为同一个算法在不同的机器上运行的时间可能是不同的,用算法的运行时间表示时间复杂度是欠妥的;

3.一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。

二.大O的渐进表示法

概念:

大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数
2、在修改后的运行次数函数中,只保留最高阶项
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

需要注意的是算法运行时可能会存在最好情况,最坏情况,平均情况,这个时候我们取最坏情况时的大O;

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

总结:

1.大O里的数就是函数表达式中对结果影响最大的项,或是最大的量级所在的项

2.如果这个项的系数不是1,那么将它变成1,简单来说,这个项前面的系数得是1

3.如果函数表达式是个常数,不管这个常数多大,都写成O( 1 )

光说不练假把式,让我们通过例题来更好的理解上述所说吧~


三.常见时间复杂度计算举例

例1

// 请计算一下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);
}

不难看出:

Func1 执行的基本操作次数 :

             F(N)=N^2+2^N+10

  N = 10        F(N) = 130
  N = 100      F(N) = 10210
  N = 1000    F(N) = 1002010

显然最大的量级是 N^2

所以时间复杂度为O(N^2)


例2

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

F(N)=2*N+10

影响最大的项为2*N,因为它的系数不是1,所以要变成1,即

时间复杂度:O(N)


例3

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

F(N)=M+N

由于并未明确告知M和N的关系,所以时间复杂度:O(M+N)

若M远大于N,则为O(M);

若N远大于M,则为O(N);

若亮着差不多大,则为O(N)或O(M);


例4

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

F(N)=100

这是一个常数,所以时间复杂度:O(1)


例5.计算冒泡排序的时间复杂度

不了解冒泡算法请戳我

// 计算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;
    }
}

最好情况:

原本已排好序,所以进入第二个for循环时不进入if语句,所以exchange==0,直接跳出循环,所以时间复杂度:O(N)

最坏情况:

执行完了所有的循环,所以时间复杂度:O(N^2)

取最坏情况,所以最终的时间复杂度为:O(N^2)

如果没有exchange相关语句,那么最好情况和最坏情况都是O(N^2)


例6.二分算法的时间复杂度

// 计算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;
}

最好情况:

第一次就找到了,所以时间复杂度:O(1)

最坏情况:

找到就剩最后一个数才找到

设数组中有N个数,一共找了X次

所以

      N/(2*2*2*2.....*2)=1

     一共X个2,即:2^X=N  ->  X=logN(注意这是一个简写,真正的意思是以2为底的N的对数)

所以取最坏情况 ,时间复杂度:O(logN)


例7.阶乘递归Fac的时间复杂度

long long Fac(size_t N)
{
    if(0 == N)
        return 1;
    return Fac(N-1)*N;
}

不难看出一共会递归N次,所以时间复杂度为:O(N)     


例8.斐波那契递归的时间复杂度

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

对于这种较复杂的时间复杂度的计算可以通过画图来观察;

 

 三角形那一块是缺失的部分;

通过上图我们发现,一共会执行F(N)=2^N-X(这个X是一个常数)

所以时间复杂度:O(2^N)


四.常见时间复杂度对比

一般算法常见的复杂度如下:

 


 五.空间复杂度

概念

1.空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度;
2.空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数;
3.空间复杂度计算规则基本跟实践复杂度类似,也使用大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;
    }
}

显然上面的代码带上形参共有5个变量,根据大O渐进法的规则,空间复杂度: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;
}

上述代码除了5个变量外,还有malloc函数开辟的n+1个空间,F(N)=n+6,

即空间复杂度:O(n)

例3

// 计算阶乘递归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/354354.html

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

相关文章

【MyBatis】| MyBatis的注解式开发

目录 一&#xff1a;MyBatis的注解式开发 1. Insert注解 2. Delete注解 3. Update注解 4. Select注解 5. Results注解 一&#xff1a;MyBatis的注解式开发 MyBatis中也提供了注解式开发⽅式&#xff0c;采⽤注解可以减少Sql映射⽂件的配置。 当然&#xff0c;使⽤注…

推荐几款好用的数据库管理工具

本文主要介绍几款常用的数据库管理软件&#xff08;客户端&#xff09;&#xff0c;包括开源/免费的、商用收费的&#xff0c;其中有一些是专用于 MySQL 数据库的&#xff0c;例如 MySQL Workbench、phpMyAdmin&#xff0c;有一些是支持多种 SQL、NoSQL 数据库的&#xff0c;例…

Kubernetes集群维护—备份恢复与升级

Etcd数据库备份与恢复 需要先安装etcd备份工具yum install etcd -y按不同安装方式执行不同备份与恢复kubeadm部署方式&#xff1a; 备份&#xff1a;ETCDCTL_API3 etcdctl snapshot save snap.db --endpointshttps://127.0.0.1:2379 --cacert/etc/kubernetes/pki/etcd/ca.cr…

知其然更要知其所以然,聊聊SQLite软件架构

SQLite是一个非常受欢迎的数据库&#xff0c;在数据库排行榜中已经进入前十的行列。这主要是因为该数据库非常小巧&#xff0c;而且可以支持Linux、Windows、iOS和Andriod的主流的操作系统。 SQLite非常简单&#xff0c;是一个进程内的动态库数据库。其最大的特点是可以支持不同…

spring的了解以及项目构建

spring理念&#xff1a; 使现有的技术更容易使用&#xff0c;其本身是一个大杂烩&#xff0c;整合了现有的技术框架。 ssh&#xff1a; struct2 spring hibernate ssm &#xff1a;springmvc spring mybatis 优点&#xff1a; spring 是一个免费的开源框架&#xff08;容器…

特征归一化(Normalization)和Batch Normalization的理解

一、理解BN必备的前置知识&#xff08;BN, LN等一系列Normalization方法的动机&#xff09; Feature Scaling&#xff08;特征归一化/Normalization&#xff09;:通俗易懂理解特征归一化对梯度下降算法的重要性 总结一下得出的结论&#xff1a; &#xff08;以下举的例子是针对…

创建基于Vue2.0开发项目的两种方式

前天开始接触基于Vue2.0的前端项目&#xff0c;实际操作中肯定会遇到一些问题&#xff0c;慢慢摸索和总结。   其实&#xff0c;作为开发一般企事业单位应用的小项目&#xff0c;前端的懂一点HTMLCSSJavaScroptJQueryJson&#xff08;或者Xml&#xff09;&#xff0c;后端懂一…

PGLBox全面解决图训练速度、成本、稳定性、复杂算法四大问题!

图神经网络&#xff08;Graph Neural Network&#xff0c;GNN&#xff09;是近年来出现的一种利用深度学习直接对图结构数据进行学习的方法&#xff0c;通过在图中的节点和边上制定聚合的策略&#xff0c;GNN能够学习到图结构数据中节点以及边内在规律和更加深层次的语义特征。…

Dubbo学习笔记2

Dubbo学习笔记&#xff08;二&#xff09; Dubbo常用配置 覆盖策略 规则&#xff1a; 1、精确优先&#xff08;方法级优先&#xff0c;接口次之&#xff0c;全局配置再次之&#xff09; 2、消费者设置优先&#xff08;如果级别一样&#xff0c;则消费方优先&#xff0c;提供…

网络安全-信息收集- 谷歌浏览器插件收集信息,谷歌hacking搜索语法-带你玩不一样的搜索引擎

网络安全-信息收集- 谷歌浏览器插件收集信息&#xff0c;谷歌hacking搜索语法-带你玩不一样的搜索引擎 前言 一&#xff0c;我也是初学者记录的笔记 二&#xff0c;可能有错误的地方&#xff0c;请谨慎 三&#xff0c;欢迎各路大神指教 四&#xff0c;任何文章仅作为学习使用 …

图解LeetCode——剑指 Offer 28. 对称的二叉树

一、题目 请实现一个函数&#xff0c;用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样&#xff0c;那么它是对称的。 二、示例 2.1> 示例 1&#xff1a; 【输入】root [1,2,2,3,4,4,3] 【输出】true 2.2> 示例 2&#xff1a; 【输入】root [1,2,2,nul…

quartz使用及原理解析

quartz简介 ​ Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;完全由Java开发&#xff0c;可以用来执行定时任务&#xff0c;类似于java.util.Timer。但是相较于Timer&#xff0c; Quartz增加了很多功能&#xff1a; 持久性作业 - 就是保持调度…

瑞典军事研究:从认知心理学的视角探讨军事创新进程

来源&#xff1a;Military Innovation as the Result of Mental Models of Technology 《摘要》 政治紧张局势的加剧和技术发展的进步促使Scandinavian 国家&#xff08;斯堪的纳维亚半岛&#xff0c;欧洲最大的半岛&#xff0c;有挪威、瑞典两国以及芬兰北端的一小部分。&am…

SpringBoot3集成TDengine自适应裂变存储

前言 首先很遗憾的告诉大家&#xff0c;今天这篇分享要关注才可以看了。原因是穷啊&#xff0c;现在基本都是要人民币玩家了&#xff0c;就比如chatGPT、copilot&#xff0c;这些AI虽然都是可以很好的辅助编码&#xff0c;但是都是要钱。入驻CSDN有些年头了&#xff0c;中间有几…

Python没有指针怎么实现链表?

Python没有指针怎么实现链表&#xff1f; 学习数据结构的的链表和树时&#xff0c;会遇到节点&#xff08;node&#xff09;这个词&#xff0c;节点是处理数据结构的链表和树的基础。节点是一种数据元素&#xff0c;包括两个部分&#xff1a;一个是实际需要用到的数据&#xff…

考研复试机试 | C++ | 尽量不要用python,很多学校不支持

目录1.1打印日期 &#xff08;清华大学上机题&#xff09;题目&#xff1a;代码&#xff1a;1.2改一改&#xff1a;上一题反过来问题代码&#xff1a;2.Day of Week &#xff08;上交&&清华机试题&#xff09;题目&#xff1a;代码&#xff1a;3.剩下的树&#xff08;清…

sni第三种模式复现、幽灵猫网络抓包方式复现、所有漏洞复现

sni第三种模式复现 搭建环境 [rootlocalhost nginx]# mkdir certificate [rootlocalhost nginx]# cd certificate/[rootlocalhost certificate]# openssl genrsa -des3 -out ssl.key 4096 [rootlocalhost certificate]# openssl req -new -key ssl.key -out aaa.csr [rootlo…

Django框架之模型视图-URLconf

URLconf 浏览者通过在浏览器的地址栏中输入网址请求网站对于Django开发的网站&#xff0c;由哪一个视图进行处理请求&#xff0c;是由url匹配找到的 配置URLconf 1.settings.py中 指定url配置 ROOT_URLCONF 项目.urls2.项目中urls.py 匹配成功后&#xff0c;包含到应用的urls…

ChatGPT时代,别再折腾孩子了

今天这篇完全是从两件事儿有感而发。昨天在文印店&#xff0c;在复印机上看到装订好的几页纸&#xff0c;我瞥了一眼&#xff0c;是历史知识点&#xff1a;隋朝大运河分为四段&#xff0c;分别是___ ___ ___ ___&#xff0c;连接了五大河___ ___ ___ ___ ______ 年&#xff…

开源云真机平台——Sonic应用实践

前言 Sonic是一款开源、支持分布式部署、在线自动化测试的私有云真机平台。想着写一篇总结分享。 一、云真机平台 1.云真机平台对比 目前市面上常见的云真机平台有两种&#xff0c;一种是各大服务商如阿里、腾讯、百度推出的公共云真机平台&#xff0c;如&#xff1a;WeTes…