【数据结构】算法的时间复杂度和空间复杂度详解

news2024/11/17 3:55:18

文章目录

  • 一、算法的效率
    • 1.1 如何衡量一个算法的好坏
    • 1.2 算法的复杂度的概念
  • 二、大O的渐进表示法
  • 三、时间复杂度
    • 2.1 时间复杂度的概念
    • 2.2常见时间复杂度计算举例
  • 四、空间复杂度
    • 2.1 空间复杂度的概念
    • 2.2常见空间复杂度计算举例
    • 五、解决问题的思路
      • LeetCode-exercise
  • 总结

一、算法的效率

1.1 如何衡量一个算法的好坏

如何衡量一个算法的好坏呢?比如对于以下斐波那契数列:
在这里插入图片描述

long long Fib(int N)
{
if(N < 3)
return 1;
return Fib(N-1) + Fib(N-2);
}
  1. 这里的时间复杂度为:2^N,计算方法请看下文。
  2. 算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。

1.2 算法的复杂度的概念

  1. 一般而言分析算法效率的方式有两种,即:时间效率和空间效率。时间效率也称为时间复杂度;空间效率也称为空间复杂度。
  2. 在计算机技术发展的几十年中,空间资源变得不是非常重要了,因此在一般的算法分析中,讨论的主要是时间复杂度,当然空间复杂度的分析也是如此。
  3. 时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。

二、大O的渐进表示法

  1. 大O符号是由德国数论学家保罗·巴赫曼(Paul Bachmann)在其1892年的著作《解析数论》(Analytische Zahlentheorie)首先引入的。
  2. “大O符号(Big Onotation)是用来描述函数渐进行为的数学符号”,假设原有的函数程序执行步为T(n),那么当T(n)=O(f(n))时,当且仅当存在正常数C和n0,使得T(n)≦C*f(n)对于所有n,n≧n0都成立。其中的f(n)这个函数用来描述原来的函数的数量级的渐进上界。使用大O符号时,用的O代表无穷大的渐进,它表示n趋近于无穷大时的一种情况。此时我们把O(f(n))称为算法的渐进时间复杂度,简称时间复杂度。时间复杂度的渐进上界表示如下图所示:
    在这里插入图片描述
  3. 当问题规模即要处理的数据增长时, 基本操作要重复执行的次数必定也会增长, 那么我们关心地是这个执行次数以什么样的数量级增长。所谓数量级可以理解为增长率。这个所谓的数量级就称为算法的渐近时间复杂度(asymptotic time complexity), 简称为时间复杂度。
  4. 食用方法:
    1.用常数1来取代运行时间中所有加法常数。
    2.修改后的运行次数函数中,只保留最高阶项
    3.如果最高阶项存在且不是1,则去除与这个项相乘的常数。
    4.在实际中一般情况关注的是算法的最坏运行情况。

三、时间复杂度

2.1 时间复杂度的概念

  1. 概念:算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述(大O渐近表示法),不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。
  2. 一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。
  3. 通俗的说,因为计算机的计算能力特别强,所以我们只需要对算法执行次数进行估算,然后再进行优化,就能有效提高算法的效率。我们只需要关心量级,而不用关心具体执行次数。
    在这里插入图片描述
    在这里插入图片描述
  1. 实例:在这里插入图片描述

2.2常见时间复杂度计算举例

实例1:

void Func(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);
}

答案:执行了M+N次,未知数M+N,最坏就是(M+N)次,数量很大,所以时间复杂度为O(M+N)

实例2:

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

答案:O(2^N)在这里插入图片描述

四、空间复杂度

2.1 空间复杂度的概念

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

2.2常见空间复杂度计算举例

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

答案: O(1)
在这里插入图片描述

实例2:O(N)

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

答案:O(N)在这里插入图片描述

五、解决问题的思路

LeetCode-exercise

  1. 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
    旋转数组

在这里插入图片描述

通过上面的学习,我们不难发现

  1. 思路一:一步一步进行旋转,其时间复杂度是O(K*N),空间复杂度为O(1) 。
  2. 思路二:创建新数组,分三步走旋转,其时间复杂度为O(N),空间复杂度为O(N)。
  3. 思路二通过空间换时间,提高了算法效率,对于如今的计算机来说,极大地存储容量,浪费的这一点空间完全是值得的。
//思路一的实现:
void rotate(int* nums, int numsSize, int k) {
	int tmp = 0;
	while (k >= numsSize)
	{
		k %= numsSize;
	}
	for (int i = 0; i < k; i++)
	{
		tmp = nums[numsSize - 1];
		for (int j = 0; j < numsSize - 1; j++)
		{
			nums[numsSize - 1-j] = nums[numsSize - 2-j];
		}
		nums[0] = tmp;
	}
}

//思路二的实现:
void rotate(int* nums, int numsSize, int k){
    k %= numsSize;
    //变长数组
    int tmp[numsSize];
    //后k个拷贝前面
    int j = 0;
    for(int i = numsSize-k ; i < numsSize ; ++i)
    {
        tmp[j] = nums[i];
        ++j;
    }
    //前n-k拷贝到后面
    for(int i = 0; i < numsSize-k ; ++i)
    {
        tmp[j] = nums[i];
        ++j;
    }
    //拷贝回去
    for(int i = 0 ; i < numsSize ; ++i)
    {
        nums[i] = tmp[i]; 
    }
}

总结

  1. 学习了数据结构以后,遇到问题的时候,我们不应该直接暴力求解,而是通过思考不同的解决方案,估算其时间复杂度和空间复杂度,选择最优解以提升算法效率。
  2. 先思考,再求解。
  3. 小伙伴们都学废了吗?在这里插入图片描述

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

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

相关文章

Html5惯性小鸟游戏制作与分享(经典游戏)

当年电子词典中的经典游戏&#xff0c;后来出了无数变种的玩法。这里还原了最初的玩法与操作。实现了这一款有点难度“的怀旧经典游戏。 玩法也很简单&#xff0c;不用碰到任何东西、持续下去。。。 可以进行试玩&#xff0c;手机玩起来效果会更好些。 点击试玩 还有很多变种…

Python小姿势 - 知识点:

知识点&#xff1a; Python的字符串格式化 标题&#xff1a; Python字符串格式化实例解析 顺便介绍一下我的另一篇专栏&#xff0c; 《100天精通Python - 快速入门到黑科技》专栏&#xff0c;是由 CSDN 内容合伙人丨全站排名 Top 4 的硬核博主 不吃西红柿 倾力打造。 基础知识…

ASO优化之竞品研究与分析

我们的应用要有绝对优势和不同的营销策略才能在应用商城里脱颖而出&#xff0c;来获取用户的注意力。我们可以通过对自己家应用与竞争对手在相似的功能和后期用户评价方面&#xff0c;提取出有助于提升应用排名的因素&#xff0c;从而确定自己家应用的优化领域。 竞品分析的主…

Debian彻底卸载软件包(apt-get)

彻底卸载软件包可以运行如下命令&#xff1a; 1 # 删除软件及其配置文件 2 apt-get --purge remove <package> 3 # 删除没用的依赖包 4 apt-get autoremove <package> 5 # 此时dpkg的列表中有“rc”状态的软件包&#xff0c;可以执行如下命令做最后清理&#xff1a…

持续集成——App自动化测试集成实战

这里写目录标题 一、app自动化测试持续集成的好处二、环境准备三、Jenkins节点挂载四、节点环境的配置1、JDK2、模拟器3、sdk环境4、Python3环境5、allure-commandline工具6、allure插件 五、本地运行待测代码(保证代码没有问题)六、库文件的导出七、Jenkins上运行代码配置1、指…

如何使用git上传文件到Github远程仓库(完整详细流程)

文章目录 1.在电脑上下载Git2.配置Git3.上传Github仓库 1.在电脑上下载Git git官网下载&#xff1a;Git - Downloads (git-scm.com) 下载后安装即可。 2.配置Git 鼠标右键进入Git命令行 &#xff08;1&#xff09;设置用户名和设置用户账号&#xff08;需要是自己的注册Git…

Floccus插件 + 坚果云 实现不同浏览器间书签同步

&#xfeff; 在工作与学习中&#xff0c;我们时常希望在不同浏览器之间实现书签的同步&#xff1b;而一些传统的浏览器书签同步方案&#xff0c;或多或少都面临着一些问题——比如&#xff0c;Chrome浏览器尽管可以实现比较好的跨设备同步&#xff0c;但由于网络的限制可能导致…

总结832

学习目标&#xff1a; 4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 学习内容&#xff1a; 暴力英语&#xff1a;读了《美丽心灵》中的经典演讲&#xff0c;回诵前3篇文章&#xff0c;默写了前3篇文章&#xff0c…

OpenCV中的图像处理3.1-3.3(三)

目录 3.1 改变色彩空间目标改变色彩空间对象跟踪如何找到HSV值来追踪&#xff1f;练习 3.2 图像的几何变换目标变换缩放平移旋转仿射变换透视变换其他资源 3.3 图像阈值处理目标简单的阈值处理自适应阈值处理Otsu的二值化Otsu的二值化是如何工作的&#xff1f;其他资源练习 翻译…

Ubuntu22.04安装CUDA、cudnn详细步骤

文章目录 安装CUDA安装cudnn下载安装文件安装验证是否安装成功 在Ubuntu系统中&#xff0c;使用nvidia-smi命令可以看到当前GPU信息&#xff0c;在右上角可以看到CUDA Version&#xff0c;意思是最大支持的CUDA版本号。 上一篇文章已经安装了显卡驱动&#xff0c;这次继续安装C…

带你深入学习k8s--(三) pod 管理

目录 一、简介 1、什么是pod 2、为什么要有pod 二、pod的分类 0、pod常用命令命令 1、准备镜像 2、自主式pod 3、控制器创建pod 4、扩容pod数量 5、通过service暴露pod&#xff08;负载均衡&#xff0c;自动发起&#xff09; 6、更新应用版本 三、编写yaml文件 四、Pod生命周期…

EF基础入门

目录 基础查询 基本单表Select查询 ​编辑 数据排序 分页Skip()、 Take() 查询聚合操作符&#xff08;如 Count、Sum、 Min、Max、Average、Aggregate&#xff09; 不返回一个序列&#xff0c;而返回一个值。 基本单表分页 基本单表 in / not in 内连接Join 左连 Grou…

基于springboot框架Java+vue2开发的智慧校园源码,智慧班牌源码

智慧校园云平台电子班牌系统源码 智慧校园平台电子班牌系统源码在大数据平台下&#xff0c;对应用系统进行统一&#xff0c;以数据互联软硬结合的特点应用在校园&#xff0c;实现对校园、班级、教师、学生的管理。 文末获取联系&#xff01; 电子班牌硬件主要用于显示班级信息…

Java SE

文章目录 基本概念cmd命令Java构成原码/反码/补码基本数据类型*switch表达式运算符三大特性关键字*对象四种关系对象的引用内存分配*接口*抽象类*内部类方法重载方法重写可变参数代码块包装类字符串* 基础知识常用APIMathSystemRuntimeObjectObjectsArraysBigIntegerBigDecimal…

node之包(第三方模块)

目录 安装包的命令 卸载包的命令 devDependencies节点 解决下包速度慢的问题 导入moment包案例 包的分类 项目包 全局包 模块的加载机制 优先从缓存中加载 内置模块的加载机制 自定义模块的加载机制 第三方模块的加载机制 目录作为模块 包是由第三方个人或团队…

c/c++:char*定义常量字符串,strcmp()函数,strcpy()函数,寻找指定字符,字符串去空格

c/c&#xff1a;char*定义常量字符串&#xff0c;strcmp()函数&#xff0c;strcpy()函数&#xff0c;寻找指定字符&#xff0c;字符串去空格 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;此时学会c的话&#xff0c; 我所…

《基于深度迁移学习的可穿戴睡眠阶段分类》阅读笔记

一、摘要 佩戴可穿戴设备进行睡眠监测是一种无创、便捷的方法&#xff0c;可以提高睡眠障碍筛查和健康监测的效率。然而&#xff0c;由于缺乏大规模、标准化的PPG数据集&#xff0c;使用PPG进行睡眠阶段分类仍然具有挑战性。本文提出了一种基于深度迁移学习的方法来解决这个问…

类对象的大小---this指针

如何计算类对象的大小 问题&#xff1a;类中既可以有成员变量&#xff0c;又可以有成员函数&#xff0c;那么一个类的对象中包含了什么&#xff1f;如何计算一个类的大小&#xff1f; 类对象的存储方式 只保存成员变量&#xff0c;成员函数存放在公共的代码段 结论&#xf…

不得不说的结构型模式-装饰器模式

目录 装饰器模式是什么 下面是装饰器模式的一个通用的类图&#xff1a; 以下是使用C实现装饰器模式的示例代码&#xff1a; 下面是面试中关于桥接器模式的常见的问题&#xff1a; 下面是问题的答案&#xff1a; 装饰器模式是什么 装饰器模式是一种结构型设计模式&#xff…

数据分析中常见标准的参考文献

做数据分析过程中&#xff0c;有些分析法方法的标准随便一搜就能找到&#xff0c;不管是口口相传还是默认&#xff0c;大家都按那样的标准做了。日常分析不细究出处还可以&#xff0c;但是正式的学术论文你需要为你写下的每一句话负责&#xff0c;每一个判断标准都应该有参考文…