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

devtools/2024/9/25 13:26:10/

时间复杂度

时间复杂度是算法效率的一个重要指标,它描述了算法运行时间与输入数据量之间的关系,给出了算法运行时间的上界估计。

时间复杂度主要关注算法中基本操作的执行次数,特别是当输入规模(通常用n表示)增大时,这些操作次数的增长趋势。在表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果为f(N),那么时间复杂度为O(f(N))。算法的时间复杂度通常为最坏情况下的时间复杂度。下面通过几个例子来说明如何计算时间复杂度:

  • 常数时间复杂度O(1):一个操作如果和样本的数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。这些操作的时间复杂度被标记为 O(1)。例如赋值操作x=1,不论给x赋值为多少,这个操作的时间都不变。

  • 线性时间复杂度O(n):

    def linear_time_example(arr):result = 0for i in range(len(arr)):result += arr[i]return result
    

    这个函数遍历数组arr的每一个元素并求和。如果数组长度为n,则循环将执行n次,因此时间复杂度为O(n)O(n)。

  • 平方时间复杂度 O(n^2)

    def quadratic_time_example(matrix):result = 0for i in range(len(matrix)):for j in range(len(matrix[i])):result += matrix[i][j]return result
    

    在这个例子中,我们有两个嵌套循环,它们都依赖于矩阵的行数(假设矩阵为方阵)。每个循环都将执行n次,所以总的操作次数为n×n=n2,因此时间复杂度为O(n2)。

  • 对数时间复杂度O(logn)

    def binary_search(arr, target):low, high = 0, len(arr) - 1while low <= high:mid = (low + high) // 2if arr[mid] == target:return midelif arr[mid] < target:low = mid + 1else:high = mid - 1return -1
    

    上述代码为二分查找实现,每次迭代,搜索范围都会减半,因此操作次数与输入大小的对数成比例,即时间复杂度为O(log⁡n)。

  • 线性对数时间复杂度O(nlogn)

    归并排序是一个典型的O(nlog⁡n)算法。它将数组分为两半,递归地排序每一半,然后合并两个有序的部分。虽然每个递归调用的时间复杂度为O(n),但由于递归深度为log⁡n,总的时间复杂度为O(nlog⁡n)。

评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是“常数项时间”。

空间复杂度

空间复杂度是衡量算法在运行过程中所需存储空间的一个指标。它描述了算法消耗的内存与输入数据量之间的关系,通常也使用大O符号(Big O notation)来表示。空间复杂度分析包括了算法运行时临时占用的额外空间,但不包括输入数据本身占用的空间(除非算法需要复制输入数据)。

以下是一些常见的空间复杂度类别:

  1. 常数空间复杂度 - O(1):算法所需的额外空间不随输入数据量的增加而改变。例如,一个简单的函数,仅使用几个变量进行计算,无论输入数据多大,所占空间都是固定的。
  2. 线性空间复杂度 - O(n):算法所需的额外空间直接与输入数据量成正比。例如,在排序算法中,如果需要创建一个与输入数组同样大小的新数组,则空间复杂度为O(n)。
  3. 对数空间复杂度 - O(log⁡n):这种空间复杂度较少见,通常发生在使用分治策略的算法中,如一些递归算法,它们可能只需要存储输入数据的层次结构,而非全部数据。
  4. 平方空间复杂度 - O(n2):如果算法需要创建一个二维数组,且每个维度的大小都与输入数据量相关,那么空间复杂度可能是O(n2)。
  5. 递归算法的空间复杂度:递归算法的空间复杂度通常由递归调用栈的深度决定。例如,二叉树的前序遍历在最坏情况下可能需要O(n)的空间,因为递归调用栈的深度可能达到树的高度。

空间复杂度中最常见的就是O(1)和O(n)。理解空间复杂度对于优化算法和系统设计非常重要,特别是在资源受限的环境中,如嵌入式系统或移动设备。有时候,为了节省空间,可能需要牺牲时间效率,反之亦然。因此,在实际应用中,经常需要在时间和空间之间做出权衡。


http://www.ppmy.cn/devtools/94187.html

相关文章

静态类+单例模式

静态类 静态类的定义 在声明类的时候加上static修饰的类为静态类。 1.静态类只允许有静态成员&#xff08;静态方法&#xff0c;静态字段&#xff0c;静态属性&#xff09;。 2.静态类不能实例化。 3.静态类中的方法是通过类名来调用。 静态类使用事项 静态类在项目中&a…

浙大数据结构慕课课后题(06-图1 列出连通集)

题目要求&#xff1a; 给定一个有n个顶点和m条边的无向图&#xff0c;请用深度优先遍历&#xff08;DFS&#xff09;和广度优先遍历&#xff08;BFS&#xff09;分别列出其所有的连通集。假设顶点从 0 到n-1编号。进行搜索时&#xff0c;假设我们总是从编号最小的顶点出发&…

【产品经理】竞品分析怎么理解?拆解一下

什么叫竞品&#xff1f;&#xff08;研究的对象&#xff09; 竞品看你怎么理解&#xff0c;有时候不一定是你的竞争对手&#xff0c;有可能是其他行业也做了这个功能&#xff0c;那你也可以学习&#xff0c;有类似的功能或者策略都可以学习&#xff0c;不过这个可能在管理学上…

Tomcat文章目录

这是一个Tomcat相关文章的目录&#xff0c;汇总了我写过的Tomcat的所有文章&#xff0c;方便进行查找回顾 第一章&#xff1a;实现一个简单的Web容器 使用Socket编程实现一个简单的服务端程序&#xff0c;但是仅仅支持静态资源&#xff08;html&#xff09;的获取。 第二章&…

2024 年 7 月公链行业研报:市场波动中 Solana 表现抢眼,Layer 2 竞争白热化

作者&#xff1a;Stella L (stellafootprint.network) 数据来源&#xff1a;Footprint Analytics 公链 Research 页面 7 月份&#xff0c;加密货币市场表现活跃&#xff0c;波动幅度较大&#xff0c;这一现象映射了全球金融市场的整体趋势。现货以太坊 ETP 在美国的上市&…

proxy负载均衡

endpoint &#xff1a; 终点、终端 看service服务器的ip kubectl get ep backend -> real server &#xff1a;真正提供web服务的服务器 负载均衡器 load balancer --》LB USER -->LB --->BACKEND(real server) nginx SERVICE --->很多的endpoint--》po…

Trie树:定义与应用

Trie树&#xff0c;也称为字典树或前缀树&#xff0c;是一种专门用于快速检索字符串集合中元素的数据结构。它在许多应用中都有广泛的使用&#xff0c;特别是在自动补全、拼写检查、词典管理和前缀匹配等场景中。本文将详细介绍Trie树的定义、构建、应用以及操作&#xff0c;并…

四十、大数据技术之Kafka3.x(3)

&#x1f33b;&#x1f33b; 目录 一、Kafka Broker1.1 Kafka Broker工作流程1.1.1 Zookeeper 存储的Kafka信息1.1.2 Kafka Broker 总体工作流程1.1.3 Broker 重要参数 1.2 生产经验——节点服役和退役1.2.1 服役新节点1.2.2 退役旧节点 1.3 Kafka 副本1.3.1 副本基本信息1.3.2…