时间复杂度和空间复杂度知识点总结

本文深入探讨算法的时间复杂度和空间复杂度,解析其衡量标准与计算方法,通过具体案例如二分查找、Fibonacci数列,阐述不同算法效率评估,助力优化算法设计。

算法:为了解决一个问题,你来写一个解决这个问题的一个方法。也就是一个一系列的计算步骤,用来将输入数据转化为输出结果。

  • 那么怎么样才能知道你写的这个算法是好的还是坏的?
    • 时间复杂度和空间复杂度就是衡量一个算法好坏的标准。时间复杂度主要衡量的就是算法的运行速度,而空间复杂度主要衡量的就是一个算法所需要的一个额外空间。

时间复杂度

  • 算法的时间复杂度是一个函数基本总的执行次数,也就是一个算法基本语句总的执行次数,关于问题规模n的数学表达式,把这个数学表达式看成算法的时间复杂度一般用f(n)表示。进而分析f(n) 随n的变化情况,这里我们使用大O渐进表示法来求取一个算法的时间复杂度。在实际中一般情况关注的是算法的最坏运行情况,也就是最坏时间复杂度。这样做的原因是:最坏情况下的时间复杂度是一个算法在任何输入实例上运行时间的上界,分析最坏的情况以估算算法指向时间的一个上界。

  • 时间复杂度看的是一个算法运行了多长时间,但是为啥最后我的衡量标准不是用时间衡量而是从一个算法基本语句总的执行次数来衡量呢?

    • 因为和环境太相关了。举个例子:假如我们进行一个冒泡排序,算法时间需要十秒。然后同样的代码放到不同的电脑上可能需要5秒。这跟一个叫做cpu主频有关,你的主频越高,你执行指令的速度就越快。

时间复杂度的分析方法:

1、时间复杂度就是一个算法基本语句总的执行次数,关于问题规模n的数学表达式。
2、一般默认的就是最坏的时间复杂度,就是分析一个算法在最坏的情况下执行的次数
例如在一个数组中找一个数字是否存在:最坏的情况就是把整个数组都遍历一遍,然后才找到那个元素,
这个就是这个算法在最坏的情况下执行的次数。
3、如果算法执行的次数是一个常数,就用O(1)表示,如果还有其它项就忽略掉常数项。
4、我们要关注运行时间的增长趋势,关注函数式中整体增长最快的一个表达式来作为保留最高阶项的依据,然后最高阶项的系数化为1。
5、计算时间复杂度是估算随着n的增长函数执行次数的增长趋势。
6、递归算法的时间复杂度为:递归的总次数每次递归中基本操作所执行的次数。

常见的时间复杂度有以下七种,算法的时间复杂度依次增加:O(1)常数型、O(log2^n)对数型、O(n)线性型、 O(nlog2 ^n)二维型、O(n ^2)平方型,O(n ^3)立方型、O(2 ^n)指数型。

空间复杂度

算法的空间复杂度就是一个算法在运行过程中临时占用存储空间大小的量度。并不是计算实际占用的空间,而是计算整个算法的辅助空间,与问题的规模没有关系。空间复杂度的计算跟时间复杂度的计算规则基本一样,也是用大O渐进表示法。

  • 递归算法的空间复杂度:递归深度N*每次递归所要的辅助空间。如果每次递归所需的辅助空间是常数,则递归的空间复杂度就是O(n)。
//计算二分查找的时间复杂度和空间复杂度
int BinarySearch(int* arr, int sz, int n) {
 assert(arr);
 int left = 0;
 int right = sz - 1;
 while (left <= right) {
  int mid = left + (right - left) / 2;
  if (arr[mid] < n) {
   left = mid + 1;
  } else if (arr[mid] > n) {
   right = mid - 1;
  } else {
   return mid;
  }
 }
 return -1;
}

在这里插入图片描述
所以二分查找的时间复杂度就为O(log2^n)。由于二分查找开辟了常数个辅助空间,所以二分查找的空间复杂度就为O(1);

//计算Fibonacci的空间复杂度和时间复杂度(非递归)
long long* Fibonacci(size_t n) {
 if (n == 0) {
  return NULL;
 }
 long long* fibArray = new long long[n + 1];//动态开辟了n+1个空间
 fibArray[0] = 0;
 fibArray[1] = 1;
 for (int i = 2; i <= n; ++i) {
  fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
 }
 return fibArray;
}

时间复杂度: for (int i = 2; i <= n; ++i)循环次数为n-1次,所以时间复杂度为O(n);
空间复杂度:n和i都是开辟了常数个空间,里面还有动态开辟了n+1个空间,所以空间复杂度为O(n);

//计算Fibonacci的时间复杂度和空间复杂度(递归)
long long Fib(int n){
	if(n<3){
	  return 1;
	}else{
	   return Fib(n-1)+fib(n-2);
	}
}

时间复杂度:
在这里插入图片描述
计算时间复杂度就是就是单次递归函数中执行次数*递归函数总的递归次数。计算上图的时间复杂度就是把他们每一层执行了多少次加起来,由于直接相加不好算,我们就把最后一层的两个结点放到上一层上,即2^0+2 ^1+…+2 ^n-3 = 2 ^n-4,所以时间复杂度就为O(2 ^n)。
空间复杂度O(n)。
对Fibonacci优化之后的时间复杂度和空间复杂度

long long Fib(long long first,long long second){
 if(n<3){
   return 1;//单次需要执行1次
 }else{
    return Fib(second,first+second,n-1);
 }
}

时间复杂度O(n);
空间复杂度:单次递归需要用到的空间*递归的深度,这个空间复杂度就是O(1),即直接在一个空间里修改。

<think>好的,用户现在问的是时间复杂度空间复杂度的区别。之前他们问过N维数组求平均函数mean的算法复杂度,我详细分析了时间空间复杂度。现在需要解释两者的区别,可能需要从定义、计算方式、影响因素等方面展开。 首先,我需要确认用户的基础知识水平。他们可能已经了解一些算法概念,但需要更清晰的对比。在之前的回答中,我已经提到过时间复杂度空间复杂度的例子,所以这里需要更系统地比较两者的不同。 用户可能是在学习算法或准备面试,所以需要明确的定义例子。要确保回答结构清晰,分点说明,可能用例子来帮助理解。同时,用户可能想知道为什么区分这两个概念很重要,实际应用中如何权衡。 我需要先给出各自的定义,然后对比它们的关注点、度量方式、优化策略实际影响。可能还需要提到它们之间的关系,比如时间-空间的权衡。注意使用之前的例子,比如mean函数的O(M)时间O(1)空间,来具体说明。 要避免使用过多术语,保持解释简单易懂。可能需要检查是否有常见的误解需要澄清,比如时间复杂度不是实际运行时间,而是增长率。同时,强调空间复杂度包括辅助空间输入本身的空间,但通常关注额外空间。 还要考虑用户可能的后续问题,比如如何分析一个算法的时间或空间复杂度,或者在实际编程中如何优化。不过当前问题只问区别,所以需要紧扣主题,不跑题。 总结时,要强调两者的重要性及平衡,让用户明白为什么需要同时考虑这两个方面。可能用比喻或类比来帮助记忆,比如时间像汽油消耗,空间像行李空间,优化方向不同。</think>--- ### **时间复杂度空间复杂度的核心区别** --- #### **1. 定义对比** | **维度** | **时间复杂度** | **空间复杂度** | |------------------|------------------------------------------------|------------------------------------------------| | **核心关注点** | **算法执行所需的时间** | **算法执行所需的内存空间** | | **度量对象** | 基本操作次数(如加减乘除、比较、循环等)的增长率 | 额外内存使用量(如变量、数组、递归栈等)的增长率 | --- #### **2. 计算方式** - **时间复杂度** 描述输入规模$n$增大时,算法执行时间的增长趋势。 **示例**: 遍历$n$个元素的数组求 → $O(n)$ 两层嵌套循环 → $O(n^2)$ - **空间复杂度** 描述输入规模$n$增大时,算法占用内存的增长趋势。 **示例**: 生成一个包含$n$个元素的数组 → $O(n)$ 仅用固定变量 → $O(1)$ --- #### **3. 关键差异** | **特征** | 时间复杂度 | 空间复杂度 | |------------------|-------------------------------------------|-------------------------------------------| | **优化方向** | 减少循环次数、优化逻辑分支 | 复用内存、减少临时变量 | | **硬件依赖** | 受CPU速度影响,但理论分析忽略具体硬件 | 受内存容量限制,但理论分析同样抽象化 | | **典型取舍** | 空间换时间(如缓存预处理数据) | 时间换空间(如流式处理替代全量存储) | | **常见表示法** | 大O符号($O(n)$, $O(n^2)$, $O(\log n)$等) | 同左 | --- #### **4. 实际案例对比** **案例**:计算斐波那契数列第$n$项 - **递归算法** - 时间复杂度:$O(2^n)$(存在重复计算) - 空间复杂度:$O(n)$(递归调用栈深度) - **动态规划算法** - 时间复杂度:$O(n)$(单次遍历) - 空间复杂度:$O(n)$(存储前$n$项结果) - **优化动态规划** - 时间复杂度:$O(n)$ - 空间复杂度:$O(1)$(仅保留最近两个值) --- #### **5. 相互关系与权衡** - **时间-空间权衡(Time-Space Tradeoff)** 多数算法需要在时间空间之间取舍: - **牺牲时间**:例如压缩数据减少内存占用,但解压需额外时间 - **牺牲空间**:例如缓存中间结果加速查询,但占用更多内存 - **现代系统倾向**: 通常更重视**时间复杂度优化**(因内存成本下降,但CPU时间直接影响用户体验) --- ### **总结** | **维度** | **时间复杂度** | **空间复杂度** | |------------------|-------------------------|-------------------------| | **本质** | 时间效率 | 内存效率 | | **优化优先级** | 通常更高 | 在资源受限时关键 | | **分析重点** | 操作次数的增长率 | 内存占用的增长率 | | **典型场景** | 大数据处理、实时系统 | 嵌入式设备、内存敏感场景 | **核心记忆点**: - 时间复杂度关注“**跑多快**”,空间复杂度关注“**占多大内存**” - 两者共同构成算法效率评价的基石,实际设计中需根据场景灵活权衡。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值